浏览代码

Document how to use screen space textures using uniform hints

clayjohn 2 年之前
父节点
当前提交
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
    <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::
 
@@ -46,8 +47,9 @@ For this demo, we will use this :ref:`Sprite <class_Sprite2D>` of a sheep.
 .. image:: img/post_example1.png
 
 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
 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;
 
     uniform vec2 size = vec2(32.0, 28.0);
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
 
     void fragment() {
             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(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:
@@ -109,17 +112,19 @@ matter.
 
     shader_type canvas_item;
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     // Blurs the screen in the X-direction.
     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;
     }
 
@@ -127,17 +132,19 @@ matter.
 
     shader_type canvas_item;
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     // Blurs the screen in the Y-direction.
     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;
     }
 

+ 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
 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
 
-    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
 and learn. One example is a simple shader to adjust brightness, contrast
 and saturation:
@@ -55,12 +56,14 @@ and saturation:
 
     shader_type canvas_item;
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     uniform float brightness = 1.0;
     uniform float contrast = 1.0;
     uniform float saturation = 1.0;
 
     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.5), c.rgb, contrast);
@@ -72,23 +75,22 @@ and saturation:
 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:
 
 .. 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>`
 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:
 
-    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.
 
 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>`
 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
 ~~~~~~~~~~~~~~~~~
 
-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:
 
--  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
    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,
-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:
 
 .. code-block:: glsl
 
+    uniform sampler2D depth_texture : hint_depth_texture, repeat_disabled, filter_nearest;
+
     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);
         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 **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.                |
 +---------------------------------------------+---------------------------------------------------------------+
@@ -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,                               |
 |                                  | **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.                                                         |
 +----------------------------------+------------------------------------------------------------------------------+

+ 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**        | 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
 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**                  |                                                                                                  |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
-| 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.                                                          |
 +----------------------------------------+--------------------------------------------------------------------------------------------------+
-| 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   |
 |                                        | 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 saturation = 1.8;
 
+    uniform sampler2D screen_texture : hint_screen_texture, repeat_disabled, filter_nearest;
+
     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.5), c.rgb, contrast);