Browse Source

Document how to use screen space textures using uniform hints

clayjohn 2 years ago
parent
commit
8bf41b6ef1

+ 29 - 22
tutorials/shaders/custom_postprocessing.rst

@@ -32,7 +32,8 @@ Your scene tree will look something like this:
 
 
    Another more efficient method is to use a :ref:`BackBufferCopy
    Another more efficient method is to use a :ref:`BackBufferCopy
    <class_BackBufferCopy>` to copy a region of the screen to a buffer and to
    <class_BackBufferCopy>` to copy a region of the screen to a buffer and to
-   access it in a shader script through ``texture(SCREEN_TEXTURE, ...)``.
+   access it in a shader script through a ``sampler2D`` using
+   ``hint_screen_texture``.
 
 
 .. note::
 .. note::
 
 
@@ -46,8 +47,9 @@ For this demo, we will use this :ref:`Sprite <class_Sprite2D>` of a sheep.
 .. image:: img/post_example1.png
 .. image:: img/post_example1.png
 
 
 Assign a new :ref:`Shader <class_Shader>` to the ``ColorRect``'s
 Assign a new :ref:`Shader <class_Shader>` to the ``ColorRect``'s
-``ShaderMaterial``. You can access the frame's texture and UV with the built in
-``SCREEN_TEXTURE`` and ``SCREEN_UV`` uniforms.
+``ShaderMaterial``. You can access the frame's texture and UV with a
+``sampler2D`` using ``hint_screen_texture`` and the built in ``SCREEN_UV``
+uniforms.
 
 
 Copy the following code to your shader. The code below is a hex pixelization
 Copy the following code to your shader. The code below is a hex pixelization
 shader by `arlez80 <https://bitbucket.org/arlez80/hex-mosaic/src/master/>`_,
 shader by `arlez80 <https://bitbucket.org/arlez80/hex-mosaic/src/master/>`_,
@@ -57,6 +59,7 @@ shader by `arlez80 <https://bitbucket.org/arlez80/hex-mosaic/src/master/>`_,
     shader_type canvas_item;
     shader_type canvas_item;
 
 
     uniform vec2 size = vec2(32.0, 28.0);
     uniform vec2 size = vec2(32.0, 28.0);
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
 
 
     void fragment() {
     void fragment() {
             vec2 norm_size = size * SCREEN_PIXEL_SIZE;
             vec2 norm_size = size * SCREEN_PIXEL_SIZE;
@@ -74,7 +77,7 @@ shader by `arlez80 <https://bitbucket.org/arlez80/hex-mosaic/src/master/>`_,
                                  float(half)),
                                  float(half)),
                              float(norm_uv.y < 0.3333333) * float(norm_uv.y / 0.3333333 < (abs(norm_uv.x - 0.5) * 2.0)));
                              float(norm_uv.y < 0.3333333) * float(norm_uv.y / 0.3333333 < (abs(norm_uv.x - 0.5) * 2.0)));
 
 
-            COLOR = textureLod(SCREEN_TEXTURE, center_uv, 0.0);
+            COLOR = textureLod(screen_texture, center_uv, 0.0);
     }
     }
 
 
 The sheep will look something like this:
 The sheep will look something like this:
@@ -109,17 +112,19 @@ matter.
 
 
     shader_type canvas_item;
     shader_type canvas_item;
 
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     // Blurs the screen in the X-direction.
     // Blurs the screen in the X-direction.
     void fragment() {
     void fragment() {
-        vec3 col = texture(SCREEN_TEXTURE, SCREEN_UV).xyz * 0.16;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(2.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(2.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(3.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(3.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(4.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(4.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
+        vec3 col = texture(screen_texture, SCREEN_UV).xyz * 0.16;
+        col += texture(screen_texture, SCREEN_UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
+        col += texture(screen_texture, SCREEN_UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
+        col += texture(screen_texture, SCREEN_UV + vec2(2.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
+        col += texture(screen_texture, SCREEN_UV + vec2(2.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
+        col += texture(screen_texture, SCREEN_UV + vec2(3.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
+        col += texture(screen_texture, SCREEN_UV + vec2(3.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
+        col += texture(screen_texture, SCREEN_UV + vec2(4.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
+        col += texture(screen_texture, SCREEN_UV + vec2(4.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
         COLOR.xyz = col;
         COLOR.xyz = col;
     }
     }
 
 
@@ -127,17 +132,19 @@ matter.
 
 
     shader_type canvas_item;
     shader_type canvas_item;
 
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     // Blurs the screen in the Y-direction.
     // Blurs the screen in the Y-direction.
     void fragment() {
     void fragment() {
-        vec3 col = texture(SCREEN_TEXTURE, SCREEN_UV).xyz * 0.16;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 2.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 3.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
-        col += texture(SCREEN_TEXTURE, SCREEN_UV + vec2(0.0, 4.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
+        vec3 col = texture(screen_texture, SCREEN_UV).xyz * 0.16;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 2.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 2.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 3.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 3.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 4.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
+        col += texture(screen_texture, SCREEN_UV + vec2(0.0, 4.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
         COLOR.xyz = col;
         COLOR.xyz = col;
     }
     }
 
 

+ 103 - 60
tutorials/shaders/screen-reading_shaders.rst

@@ -17,36 +17,37 @@ The workaround is to make a copy of the screen, or a part of the screen,
 to a back-buffer and then read from it while drawing. Godot provides a
 to a back-buffer and then read from it while drawing. Godot provides a
 few tools that make this process easy.
 few tools that make this process easy.
 
 
-SCREEN_TEXTURE built-in texture
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Screen texture
+~~~~~~~~~~~~~~
 
 
-Godot :ref:`doc_shading_language` has a special texture, ``SCREEN_TEXTURE`` (and ``DEPTH_TEXTURE`` for depth, in the case of 3D).
-It takes as argument the UV of the screen and returns a vec3 RGB with the color. A
-special built-in varying: SCREEN_UV can be used to obtain the UV for
-the current fragment. As a result, this canvas_item fragment shader results in an invisible object,
-because it only shows what lies behind:
+Godot :ref:`doc_shading_language` has a special texture to access the already
+rendered contents of the screen. It is used by specifying a hint when declaring
+a ``sampler2D`` uniform: ``hint_screen_texture``. A special built-in varying
+``SCREEN_UV`` can be used to obtain the UV relative to the screen for the current
+fragment. As a result, this canvas_item fragment shader results in an invisible
+object, because it only shows what lies behind:
 
 
 .. code-block:: glsl
 .. code-block:: glsl
 
 
-    void fragment() {
-        COLOR = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
-    }
-
-The reason why textureLod must be used is because, when Godot copies back
-a chunk of the screen, it also does an efficient separable gaussian blur to its mipmaps.
+    shader_type canvas_item;
 
 
-This allows for not only reading from the screen, but reading from it with different amounts
-of blur at no cost.
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
 
 
-.. note::
+    void fragment() {
+        COLOR = textureLod(screen_texture, SCREEN_UV, 0.0);
+    }
 
 
-   Mipmaps are not generated in GLES2 due to poor performance and compatibility with older
-   devices.
+``textureLod`` is used here as we only want to read from the bottom mipmap. If
+you want to read from a blurred version of the texture instead, you can increase
+the third argument to ``textureLod`` and change the hint ``filter_nearest`` to
+``filter_nearest_mipmap`` (or any other filter with mipmaps enabled). If using a
+filter with mipmaps, Godot will automatically calculate the blurred texture for
+you.
 
 
-SCREEN_TEXTURE example
+Screen texture example
 ~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~
 
 
-``SCREEN_TEXTURE`` can be used for many things. There is a
+The screen texture can be used for many things. There is a
 special demo for *Screen Space Shaders*, that you can download to see
 special demo for *Screen Space Shaders*, that you can download to see
 and learn. One example is a simple shader to adjust brightness, contrast
 and learn. One example is a simple shader to adjust brightness, contrast
 and saturation:
 and saturation:
@@ -55,12 +56,14 @@ and saturation:
 
 
     shader_type canvas_item;
     shader_type canvas_item;
 
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     uniform float brightness = 1.0;
     uniform float brightness = 1.0;
     uniform float contrast = 1.0;
     uniform float contrast = 1.0;
     uniform float saturation = 1.0;
     uniform float saturation = 1.0;
 
 
     void fragment() {
     void fragment() {
-        vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb;
+        vec3 c = textureLod(screen_texture, SCREEN_UV, 0.0).rgb;
 
 
         c.rgb = mix(vec3(0.0), c.rgb, brightness);
         c.rgb = mix(vec3(0.0), c.rgb, brightness);
         c.rgb = mix(vec3(0.5), c.rgb, contrast);
         c.rgb = mix(vec3(0.5), c.rgb, contrast);
@@ -72,23 +75,22 @@ and saturation:
 Behind the scenes
 Behind the scenes
 ~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~
 
 
-While this seems magical, it's not. In 2D, the ``SCREEN_TEXTURE`` built-in, when
-first found in a node that is about to be drawn, does a full-screen
-copy to a back-buffer. Subsequent nodes that use it in
-shaders will not have the screen copied for them, because this ends up
-being inefficient. In 3D, the screen is copied after the opaque geometry pass,
-but before the transparent geometry pass, so transparent objects will not be
-captured in the ``SCREEN_TEXTURE``.
+While this seems magical, it's not. In 2D, when ``hint_screen_texture`` is first
+found in a node that is about to be drawn, Godot does a full-screen copy to a
+back-buffer. Subsequent nodes that use it in shaders will not have the screen
+copied for them, because this ends up being inefficient. In 3D, the screen is
+copied after the opaque geometry pass, but before the transparent geometry pass,
+so transparent objects will not be captured in the screen texture.
 
 
-As a result, in 2D, if shaders that use ``SCREEN_TEXTURE`` overlap, the second one
-will not use the result of the first one, resulting in unexpected
+As a result, in 2D, if shaders that use ``hint_screen_texture`` overlap, the
+second one will not use the result of the first one, resulting in unexpected
 visuals:
 visuals:
 
 
 .. image:: img/texscreen_demo1.png
 .. image:: img/texscreen_demo1.png
 
 
-In the above image, the second sphere (top right) is using the same
-source for ``SCREEN_TEXTURE`` as the first one below, so the first one
-"disappears", or is not visible.
+In the above image, the second sphere (top right) is using the same source for
+the screen texture as the first one below, so the first one "disappears", or is
+not visible.
 
 
 In 2D, this can be corrected via the :ref:`BackBufferCopy <class_BackBufferCopy>`
 In 2D, this can be corrected via the :ref:`BackBufferCopy <class_BackBufferCopy>`
 node, which can be instantiated between both spheres. BackBufferCopy can work by
 node, which can be instantiated between both spheres. BackBufferCopy can work by
@@ -102,56 +104,97 @@ With correct back-buffer copying, the two spheres blend correctly:
 
 
 .. warning:
 .. warning:
 
 
-    Materials that use ``SCREEN_TEXTURE`` are considered transparent themselves and
-    will not appear in the resulting ``SCREEN_TEXTURE`` of other materials.
-    If you plan to instance a scene that uses a material with ``SCREEN_TEXTURE``,
+    In 3D, materials that use ``hint_screen_texture`` are considered transparent themselves and
+    will not appear in the resulting screen texture of other materials.
+    If you plan to instance a scene that uses a material with ``hint_screen_texture``,
     you will need to use a BackBufferCopy node.
     you will need to use a BackBufferCopy node.
 
 
 In 3D, there is less flexibility to solve this particular issue because the
 In 3D, there is less flexibility to solve this particular issue because the
-``SCREEN_TEXTURE`` is only captured once. Be careful when using
-``SCREEN_TEXTURE`` in 3D as it won't capture transparent objects and may capture
-some opaque objects that are in front of the object.
+screen texture is only captured once. Be careful when using the screen texture
+in 3D as it won't capture transparent objects and may capture some opaque
+objects that are in front of the object using the screen texture.
 
 
 You can reproduce the back-buffer logic in 3D by creating a :ref:`Viewport <class_Viewport>`
 You can reproduce the back-buffer logic in 3D by creating a :ref:`Viewport <class_Viewport>`
 with a camera in the same position as your object, and then use the
 with a camera in the same position as your object, and then use the
-:ref:`Viewport's <class_Viewport>` texture instead of ``SCREEN_TEXTURE``.
+:ref:`Viewport's <class_Viewport>` texture instead of the screen texture.
 
 
 Back-buffer logic
 Back-buffer logic
 ~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~
 
 
-So, to make it clearer, here's how the backbuffer copying logic works in
+So, to make it clearer, here's how the backbuffer copying logic works in 2D in
 Godot:
 Godot:
 
 
--  If a node uses the ``SCREEN_TEXTURE``, the entire screen is copied to the
+-  If a node uses ``hint_screen_texture``, the entire screen is copied to the
    back buffer before drawing that node. This only happens the first
    back buffer before drawing that node. This only happens the first
    time; subsequent nodes do not trigger this.
    time; subsequent nodes do not trigger this.
--  If a BackBufferCopy node was processed before the situation in the
-   point above (even if ``SCREEN_TEXTURE`` was not used), the behavior
-   described in the point above does not happen. In other words,
-   automatic copying of the entire screen only happens if ``SCREEN_TEXTURE`` is
-   used in a node for the first time and no BackBufferCopy node (not
-   disabled) was found before in tree-order.
--  BackBufferCopy can copy either the entire screen or a region. If set
-   to only a region (not the whole screen) and your shader uses pixels
-   not in the region copied, the result of that read is undefined
-   (most likely garbage from previous frames). In other words, it's
-   possible to use BackBufferCopy to copy back a region of the screen
-   and then use ``SCREEN_TEXTURE`` on a different region. Avoid this behavior!
-
-
-DEPTH_TEXTURE
+-  If a BackBufferCopy node was processed before the situation in the point
+   above (even if ``hint_screen_texture`` was not used), the behavior described
+   in the point above does not happen. In other words, automatic copying of the
+   entire screen only happens if ``hint_screen_texture`` is used in a node for
+   the first time and no BackBufferCopy node (not disabled) was found before in
+   tree-order.
+-  BackBufferCopy can copy either the entire screen or a region. If set to only
+   a region (not the whole screen) and your shader uses pixels not in the region
+   copied, the result of that read is undefined (most likely garbage from
+   previous frames). In other words, it's possible to use BackBufferCopy to copy
+   back a region of the screen and then read the screen texture from a different
+   region. Avoid this behavior!
+
+
+Depth texture
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
 
 
 For 3D shaders, it's also possible to access the screen depth buffer. For this,
 For 3D shaders, it's also possible to access the screen depth buffer. For this,
-the ``DEPTH_TEXTURE`` built-in is used. This texture is not linear; it must be
-converted via the inverse projection matrix.
+the ``hint_depth_texture`` hint is used. This texture is not linear; it must be
+converted using the inverse projection matrix.
 
 
 The following code retrieves the 3D position below the pixel being drawn:
 The following code retrieves the 3D position below the pixel being drawn:
 
 
 .. code-block:: glsl
 .. code-block:: glsl
 
 
+    uniform sampler2D depth_texture : hint_depth_texture, repeat_disabled, filter_nearest;
+
     void fragment() {
     void fragment() {
-        float depth = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;
+        float depth = textureLod(depth_texture, SCREEN_UV, 0.0).r;
         vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
         vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
         vec3 pixel_position = upos.xyz / upos.w;
         vec3 pixel_position = upos.xyz / upos.w;
     }
     }
+
+Normal-roughness texture
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Similarly, the normal-roughness texture can be used to read the normals and
+roughness of objects rendered in the depth prepass. The normal is stored in the
+``.xyz`` channels (mapped to the 0-1 range) while the roughness is stored in the
+``.w`` channel.
+
+.. code-block:: glsl
+
+    uniform sampler2D normal_roughness_texture : hint_normal_roughness_texture, repeat_disabled, filter_nearest;
+
+    void fragment() {
+        float screen_roughness = texture(normal_roughness_texture, SCREEN_UV).w;
+        vec3 screen_normal = texture(normal_roughness_texture, SCREEN_UV).xyz;
+        screen_normal = screen_normal * 2.0 - 1.0;
+
+Redefining screen textures
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The screen texture hints (``hint_screen_texture``, ``hint_depth_texture``, and
+``hint_normal_roughness_texture``) can be used with multiple uniforms. For
+example, you may want to read from the texture multiple times with a different
+repeat flag or filter flag.
+
+The following example shows a shader that reads the screen space normal with
+linear filtering, but reads the screen space roughness using nearest neighbor
+filtering.
+
+.. code-block:: glsl
+
+    uniform sampler2D normal_roughness_texture : hint_normal_roughness_texture, repeat_disabled, filter_nearest;
+    uniform sampler2D normal_roughness_texture2 : hint_normal_roughness_texture, repeat_enabled, filter_linear;
+
+    void fragment() {
+        float screen_roughness = texture(normal_roughness_texture, SCREEN_UV).w;
+        vec3 screen_normal = texture(normal_roughness_texture2, SCREEN_UV).xyz;
+        screen_normal = screen_normal * 2.0 - 1.0;

+ 4 - 3
tutorials/shaders/shader_reference/canvas_item_shader.rst

@@ -172,9 +172,10 @@ it to the ``NORMALMAP`` property. Godot will handle converting it for use in 2D
 +---------------------------------------------+---------------------------------------------------------------+
 +---------------------------------------------+---------------------------------------------------------------+
 | in vec2 **UV**                              | UV from vertex function.                                      |
 | in vec2 **UV**                              | UV from vertex function.                                      |
 +---------------------------------------------+---------------------------------------------------------------+
 +---------------------------------------------+---------------------------------------------------------------+
-| in vec2 **SCREEN_UV**                       | Screen UV for use with **SCREEN_TEXTURE**.                    |
+| in vec2 **SCREEN_UV**                       | Screen UV coordinate for current pixel.                       |
 +---------------------------------------------+---------------------------------------------------------------+
 +---------------------------------------------+---------------------------------------------------------------+
-| sampler2D **SCREEN_TEXTURE**                | Screen texture, mipmaps contain gaussian blurred versions.    |
+| sampler2D **SCREEN_TEXTURE**                | Removed in Godot 4. Use a ``sampler2D`` with                  |
+|                                             | ``hint_screen_texture`` instead.                              |
 +---------------------------------------------+---------------------------------------------------------------+
 +---------------------------------------------+---------------------------------------------------------------+
 | inout vec3 **NORMAL**                       | Normal read from **NORMAL_TEXTURE**. Writable.                |
 | inout vec3 **NORMAL**                       | Normal read from **NORMAL_TEXTURE**. Writable.                |
 +---------------------------------------------+---------------------------------------------------------------+
 +---------------------------------------------+---------------------------------------------------------------+
@@ -236,7 +237,7 @@ Below is an example of a light shader that takes a CanvasItem's normal map into
 |                                  | For a Sprite2D with a texture of size 64x32px,                               |
 |                                  | For a Sprite2D with a texture of size 64x32px,                               |
 |                                  | **TEXTURE_PIXEL_SIZE** = :code:`vec2(1/64, 1/32)`                            |
 |                                  | **TEXTURE_PIXEL_SIZE** = :code:`vec2(1/64, 1/32)`                            |
 +----------------------------------+------------------------------------------------------------------------------+
 +----------------------------------+------------------------------------------------------------------------------+
-| in vec2 **SCREEN_UV**            | **SCREEN_TEXTURE** Coordinate (for using with screen texture).               |
+| in vec2 **SCREEN_UV**            | Screen UV coordinate for current pixel.                                      |
 +----------------------------------+------------------------------------------------------------------------------+
 +----------------------------------+------------------------------------------------------------------------------+
 | in vec2 **POINT_COORD**          | UV for Point Sprite.                                                         |
 | in vec2 **POINT_COORD**          | UV for Point Sprite.                                                         |
 +----------------------------------+------------------------------------------------------------------------------+
 +----------------------------------+------------------------------------------------------------------------------+

+ 6 - 0
tutorials/shaders/shader_reference/shading_language.rst

@@ -783,6 +783,12 @@ Full list of hints below:
 +----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
 +----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
 | **sampler2D**        | repeat[_enable, _disable]                        | Enabled texture repeating.                                                  |
 | **sampler2D**        | repeat[_enable, _disable]                        | Enabled texture repeating.                                                  |
 +----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
 +----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
+| **sampler2D**        | hint_screen_texture                              | Texture is the screen texture.                                              |
++----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
+| **sampler2D**        | hint_depth_texture                               | Texture is the depth texture.                                               |
++----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
+| **sampler2D**        | hint_normal_roughness_texture                    | Texture is the normal roughness texture.                                    |
++----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+
 
 
 GDScript uses different variable types than GLSL does, so when passing variables
 GDScript uses different variable types than GLSL does, so when passing variables
 from GDScript to shaders, Godot converts the type automatically. Below is a
 from GDScript to shaders, Godot converts the type automatically. Below is a

+ 2 - 4
tutorials/shaders/shader_reference/spatial_shader.rst

@@ -289,13 +289,11 @@ these properties, and if you don't write to them, Godot will optimize away the c
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 | in int **VIEW_RIGHT**                  |                                                                                                  |
 | in int **VIEW_RIGHT**                  |                                                                                                  |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
-| sampler2D **SCREEN_TEXTURE**           | Built-in Texture for reading from the screen. Mipmaps contain increasingly blurred copies.       |
+| sampler2D **SCREEN_TEXTURE**           | Removed in Godot 4. Use a ``sampler2D`` with ``hint_screen_texture`` instead.                    |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 | in vec2 **SCREEN_UV**                  | Screen UV coordinate for current pixel.                                                          |
 | in vec2 **SCREEN_UV**                  | Screen UV coordinate for current pixel.                                                          |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
-| sampler2D **NORMAL_ROUGHNESS_TEXTURE** |                                                                                                  |
-+----------------------------------------+--------------------------------------------------------------------------------------------------+
-| sampler2D **DEPTH_TEXTURE**            | Built-in Texture for reading depth from the screen. Must convert to linear using INV_PROJECTION. |
+| sampler2D **DEPTH_TEXTURE**            | Removed in Godot 4. Use a ``sampler2D`` with ``hint_depth_texture`` instead.                     |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
 | out float **DEPTH**                    | Custom depth value (0..1). If ``DEPTH`` is being written to in any shader branch, then you are   |
 | out float **DEPTH**                    | Custom depth value (0..1). If ``DEPTH`` is being written to in any shader branch, then you are   |
 |                                        | responsible for setting the ``DEPTH`` for **all** other branches. Otherwise, the graphics API    |
 |                                        | responsible for setting the ``DEPTH`` for **all** other branches. Otherwise, the graphics API    |

+ 3 - 1
tutorials/shaders/shaders_style_guide.rst

@@ -36,8 +36,10 @@ Here is a complete shader example based on these guidelines:
     uniform float contrast = 1.5;
     uniform float contrast = 1.5;
     uniform float saturation = 1.8;
     uniform float saturation = 1.8;
 
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     void fragment() {
     void fragment() {
-        vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb;
+        vec3 c = textureLod(screen_texture, SCREEN_UV, 0.0).rgb;
 
 
         c.rgb = mix(vec3(0.0), c.rgb, brightness);
         c.rgb = mix(vec3(0.0), c.rgb, brightness);
         c.rgb = mix(vec3(0.5), c.rgb, contrast);
         c.rgb = mix(vec3(0.5), c.rgb, contrast);