Introduction

Pausing your game in Godot is, as you can see from official docs, quite easy.

In my project I make use of a lot of different shaders and I, incorrectly,
assumed that when you pause a game, the shaders would pause along
with the rest of the nodes. Turns out shaders are programs that are
always running on the GPU and never stop, unless you add specific logic
to the shader to support this.

Solution

So I had to come up with another solution (more of a cheat really):

  1. When you pause the game, capture the screen.
  2. Take the resulting texture and assign it to the texture property
    of an TextureRect which is displayed over the original shader.

Scene Setup

Image the following scene with a ColorRect and a TextureRect.
The ColorRect displays the shader.
The TextureRect will display the frozen shader.

    Node2D
    |--ColorRect : Shader
    |--TextureRect : PauseNode (hidden)

The code

I’m a c# guy but it’s very easy to translate this to gdscript.
Imagine the following method that toggles the paused state.

public void TogglePause()
{
    var pauseNode = GetNode<TextureRect>("PauseNode");
    if (!pauseNode.Visible)
    {
        viewport.RenderTargetClearMode = Viewport.ClearMode.OnlyNextFrame;
        pauseNode.Texture = viewport.GetTexture();
        pauseNode.Visible = true;
    }
    else
    {    
        viewport.RenderTargetClearMode = Viewport.ClearMode.Always;
        pauseNode.Texture?.Dispose();
        pauseNode.Visible = false;
    }
}
Pausing

First you have to get the ViewPort and set the RenderTargetClearMode
to ClearMode.OnlyNextFrame. Next you get the Texture and
assign it to the Texture property of the TextureRect.

Resuming

Simply reverse the procedure and you’re done.