From 3ee7142208845464b094caf113a1ae39e4801448 Mon Sep 17 00:00:00 2001 From: tetrapod00 <145553014+tetrapod00@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:01:02 -0800 Subject: [PATCH] Reorganize and improve shader Uniforms section --- .../shader_reference/shading_language.rst | 341 ++++++++++-------- 1 file changed, 181 insertions(+), 160 deletions(-) diff --git a/tutorials/shaders/shader_reference/shading_language.rst b/tutorials/shaders/shader_reference/shading_language.rst index d2a9e44cc73..222a64f927c 100644 --- a/tutorials/shaders/shader_reference/shading_language.rst +++ b/tutorials/shaders/shader_reference/shading_language.rst @@ -14,6 +14,8 @@ If you are already familiar with GLSL, the :ref:`Godot Shader Migration Guide` is a resource that will help you transition from regular GLSL to Godot's shading language. +.. _doc_shading_language_data_types: + Data types ---------- @@ -813,10 +815,11 @@ There are two possible interpolation qualifiers: Uniforms -------- -Passing values to shaders is possible. These are global to the whole shader and -are called *uniforms*. When a shader is later assigned to a material, the -uniforms will appear as editable parameters in it. Uniforms can't be written -from within the shader. Any GLSL type except for ``void`` can be a uniform. +Passing values to shaders is possible with *uniforms*, which are defined in the +global scope of the shader, outside of functions. When a shader is later +assigned to a material, the uniforms will appear as editable parameters in the +material's inspector. Uniforms can't be written from within the shader. Any +:ref:`data type ` except for ``void`` can be a uniform. .. code-block:: glsl @@ -826,49 +829,8 @@ from within the shader. Any GLSL type except for ``void`` can be a uniform. uniform vec3 colors[3]; -You can set uniforms in the editor in the material. Or you can set them through -GDScript: - -.. code-block:: gdscript - - material.set_shader_parameter("some_value", some_value) - - material.set_shader_parameter("colors", [Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)]) - -You can access ``int`` values as a readable dropdown widget using the ``hint_enum`` uniform: - -.. code-block:: glsl - - uniform int noise_type : hint_enum("OpenSimplex2", "Cellular", "Perlin", "Value") = 0; - -.. note:: Unlike ``@export_enum`` in GDScript, the ``hint_enum`` uniform does not support - the use of ``String``\ s, it only supports ``int``\ s. - -You can assign explicit values to the ``hint_enum`` uniform using colon syntax similar to GDScript: - -.. code-block:: glsl - - uniform int character_speed: hint_enum("Slow:30", "Average:60", "Very Fast:200") = 60; - -The value will be stored as an integer, corresponding to the index of the selected option (i.e. 0, 1, or 2) -or the value assigned by colon syntax (i.e. 30, 60, or 200). - -.. note:: The first argument to ``set_shader_parameter`` is the name of the uniform - in the shader. It must match *exactly* to the name of the uniform in - the shader or else it will not be recognized. - -.. note:: There is a limit to the total size of shader uniforms that you can use - in a single shader. On most desktop platforms, this limit is ``65536`` - bytes, or 4096 ``vec4`` uniforms. On mobile platforms, the limit is - typically ``16384`` bytes, or 1024 ``vec4`` uniforms. Vector uniforms - smaller than a ``vec4``, such as ``vec2`` or ``vec3``, are padded to - the size of a ``vec4``. Scalar uniforms such as ``int`` or ``float`` - are not padded, and ``bool`` is padded to the size of an ``int``. - - Arrays count as the total size of their contents. If you need a uniform - array that is larger than this limit, consider packing the data into a - texture instead, since the *contents* of a texture do not count towards - this limit, only the size of the sampler uniform. +You can set uniforms in the editor in the material's inspector. Alternately, you +can set them :ref:`from code `. Uniform hints ~~~~~~~~~~~~~ @@ -885,24 +847,16 @@ uniform is used for, and how the editor should allow users to modify it. uniform vec4 other_color : source_color = vec4(1.0); // Default values go after the hint. uniform sampler2D image : source_color; -.. admonition:: Source Color +Uniforms can also be assigned default values: - Any texture which contains *sRGB color data* requires a ``source_color`` hint - in order to be correctly sampled. This is because Godot renders in linear - color space, but some textures contain sRGB color data. If this hint is not - used, the texture will appear washed out. +.. code-block:: glsl - Albedo and color textures should typically have a ``source_color`` hint. Normal, - roughness, metallic, and height textures typically do not need a ``source_color`` - hint. + shader_type spatial; - Using ``source_color`` hint is required in the Forward+ and Mobile renderers, - and in ``canvas_item`` shaders when :ref:`HDR 2D` - is enabled. The ``source_color`` hint is optional for the Compatibility renderer, - and for ``canvas_item`` shaders if ``HDR 2D`` is disabled. However, it is - recommended to always use the ``source_color`` hint, because it works even - if you change renderers or disable ``HDR 2D``. + uniform vec4 some_vector = vec4(0.0); + uniform vec4 some_color : source_color = vec4(1.0); +Note that when adding a default value and a hint, the default value goes after the hint. Full list of uniform hints below: @@ -942,114 +896,51 @@ Full list of uniform hints below: | **sampler2D** | hint_normal_roughness_texture | Texture is the normal roughness texture (only supported in Forward+). | +----------------------+--------------------------------------------------+-----------------------------------------------------------------------------+ -GDScript uses different variable types than GLSL does, so when passing variables -from GDScript to shaders, Godot converts the type automatically. Below is a -table of the corresponding types: +Using ``hint_enum`` +^^^^^^^^^^^^^^^^^^^ -+------------------------+-------------------------+------------------------------------------------------------+ -| GLSL type | GDScript type | Notes | -+========================+=========================+============================================================+ -| **bool** | **bool** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **bvec2** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | -| | | | -| | | For example, a bvec2 of (bx, by) could be created in | -| | | the following way: | -| | | | -| | | .. code-block:: gdscript | -| | | | -| | | bvec2_input: int = (int(bx)) | (int(by) << 1) | -| | | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **bvec3** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | -+------------------------+-------------------------+------------------------------------------------------------+ -| **bvec4** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | -+------------------------+-------------------------+------------------------------------------------------------+ -| **int** | **int** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **ivec2** | **Vector2i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **ivec3** | **Vector3i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **ivec4** | **Vector4i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **uint** | **int** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **uvec2** | **Vector2i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **uvec3** | **Vector3i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **uvec4** | **Vector4i** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **float** | **float** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **vec2** | **Vector2** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **vec3** | **Vector3**, **Color** | When Color is used, it will be interpreted as (r, g, b). | -+------------------------+-------------------------+------------------------------------------------------------+ -| **vec4** | **Vector4**, **Color**, | When Color is used, it will be interpreted as (r, g, b, a).| -| | **Rect2**, **Plane**, | | -| | **Quaternion** | When Rect2 is used, it will be interpreted as | -| | | (position.x, position.y, size.x, size.y). | -| | | | -| | | When Plane is used it will be interpreted as | -| | | (normal.x, normal.y, normal.z, d). | -| | | | -| | | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **mat2** | **Transform2D** | | -| | | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **mat3** | **Basis** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **mat4** | **Projection**, | When a Transform3D is used, the w Vector is set to the | -| | **Transform3D** | identity. | -+------------------------+-------------------------+------------------------------------------------------------+ -| **sampler2D** | **Texture2D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **isampler2D** | **Texture2D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **usampler2D** | **Texture2D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **sampler2DArray** | **Texture2DArray** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **isampler2DArray** | **Texture2DArray** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **usampler2DArray** | **Texture2DArray** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **sampler3D** | **Texture3D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **isampler3D** | **Texture3D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **usampler3D** | **Texture3D** | | -+------------------------+-------------------------+------------------------------------------------------------+ -| **samplerCube** | **Cubemap** | See :ref:`doc_importing_images_changing_import_type` for | -| | | instructions on importing cubemaps for use in Godot. | -+------------------------+-------------------------+------------------------------------------------------------+ -| **samplerCubeArray** | **CubemapArray** | Only supported in Forward+ and Mobile, not Compatibility. | -+------------------------+-------------------------+------------------------------------------------------------+ -| **samplerExternalOES** | **ExternalTexture** | Only supported in Compatibility/Android platform. | -+------------------------+-------------------------+------------------------------------------------------------+ +You can access ``int`` values as a readable dropdown widget using the ``hint_enum`` uniform: -.. note:: Be careful when setting shader uniforms from GDScript, no error will - be thrown if the type does not match. Your shader will just exhibit - undefined behavior. +.. code-block:: -.. warning:: - As with the last note, no error will be thrown if the typing does not match while setting a shader uniform, this unintuitively includes setting a (GDscript) 64 bit int/float into a Godot shader language int/float (32 bit). This may lead to unintentional consequences in cases where high precision is required. + uniform int noise_type : hint_enum("OpenSimplex2", "Cellular", "Perlin", "Value") = 0; -Uniforms can also be assigned default values: +You can assign explicit values to the ``hint_enum`` uniform using colon syntax similar to GDScript: -.. code-block:: glsl +.. code-block:: + + uniform int character_speed: hint_enum("Slow:30", "Average:60", "Very Fast:200") = 60; - shader_type spatial; +The value will be stored as an integer, corresponding to the index of the selected +option (i.e. ``0``, ``1``, or ``2``) or the value assigned by colon syntax +(i.e. ``30``, ``60``, or ``200``). When setting the value with +``set_shader_parameter()``, you must use the integer value, not the ``String`` +name. - uniform vec4 some_vector = vec4(0.0); - uniform vec4 some_color : source_color = vec4(1.0); +Using ``source_color`` +^^^^^^^^^^^^^^^^^^^^^^ -Note that when adding a default value and a hint, the default value goes after the hint. +Any texture which contains *sRGB color data* requires a ``source_color`` hint +in order to be correctly sampled. This is because Godot renders in linear +color space, but some textures contain sRGB color data. If this hint is not +used, the texture will appear washed out. + +Albedo and color textures should typically have a ``source_color`` hint. Normal, +roughness, metallic, and height textures typically do not need a ``source_color`` +hint. + +Using ``source_color`` hint is required in the Forward+ and Mobile renderers, +and in ``canvas_item`` shaders when :ref:`HDR 2D` +is enabled. The ``source_color`` hint is optional for the Compatibility renderer, +and for ``canvas_item`` shaders if ``HDR 2D`` is disabled. However, it is +recommended to always use the ``source_color`` hint, because it works even +if you change renderers or disable ``HDR 2D``. -If you need to make multiple uniforms to be grouped in the specific category of an inspector, you can use a `group_uniform` keyword like: +Uniform groups +~~~~~~~~~~~~~~ + +To group multiple uniforms in a section in the inspector, you can use a +``group_uniform`` keyword like this: .. code-block:: glsl @@ -1219,6 +1110,136 @@ When using per-instance uniforms, there are some restrictions you should be awar instance uniform vec4 my_color : source_color, instance_index(5); +.. _doc_shading_language_setting_uniforms_from_code: + +Setting uniforms from code +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can set uniforms from GDScript: + +.. code-block:: gdscript + + material.set_shader_parameter("some_value", some_value) + + material.set_shader_parameter("colors", [Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)]) + +.. note:: The first argument to ``set_shader_parameter`` is the name of the uniform + in the shader. It must match *exactly* to the name of the uniform in + the shader or else it will not be recognized. + +GDScript uses different variable types than GLSL does, so when passing variables +from GDScript to shaders, Godot converts the type automatically. Below is a +table of the corresponding types: + ++------------------------+-------------------------+------------------------------------------------------------+ +| GLSL type | GDScript type | Notes | ++========================+=========================+============================================================+ +| **bool** | **bool** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **bvec2** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | +| | | | +| | | For example, a bvec2 of (bx, by) could be created in | +| | | the following way: | +| | | | +| | | .. code-block:: gdscript | +| | | | +| | | bvec2_input: int = (int(bx)) | (int(by) << 1) | +| | | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **bvec3** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | ++------------------------+-------------------------+------------------------------------------------------------+ +| **bvec4** | **int** | Bitwise packed int where bit 0 (LSB) corresponds to x. | ++------------------------+-------------------------+------------------------------------------------------------+ +| **int** | **int** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **ivec2** | **Vector2i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **ivec3** | **Vector3i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **ivec4** | **Vector4i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **uint** | **int** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **uvec2** | **Vector2i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **uvec3** | **Vector3i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **uvec4** | **Vector4i** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **float** | **float** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **vec2** | **Vector2** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **vec3** | **Vector3**, **Color** | When Color is used, it will be interpreted as (r, g, b). | ++------------------------+-------------------------+------------------------------------------------------------+ +| **vec4** | **Vector4**, **Color**, | When Color is used, it will be interpreted as (r, g, b, a).| +| | **Rect2**, **Plane**, | | +| | **Quaternion** | When Rect2 is used, it will be interpreted as | +| | | (position.x, position.y, size.x, size.y). | +| | | | +| | | When Plane is used it will be interpreted as | +| | | (normal.x, normal.y, normal.z, d). | +| | | | +| | | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **mat2** | **Transform2D** | | +| | | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **mat3** | **Basis** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **mat4** | **Projection**, | When a Transform3D is used, the w Vector is set to the | +| | **Transform3D** | identity. | ++------------------------+-------------------------+------------------------------------------------------------+ +| **sampler2D** | **Texture2D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **isampler2D** | **Texture2D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **usampler2D** | **Texture2D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **sampler2DArray** | **Texture2DArray** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **isampler2DArray** | **Texture2DArray** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **usampler2DArray** | **Texture2DArray** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **sampler3D** | **Texture3D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **isampler3D** | **Texture3D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **usampler3D** | **Texture3D** | | ++------------------------+-------------------------+------------------------------------------------------------+ +| **samplerCube** | **Cubemap** | See :ref:`doc_importing_images_changing_import_type` for | +| | | instructions on importing cubemaps for use in Godot. | ++------------------------+-------------------------+------------------------------------------------------------+ +| **samplerCubeArray** | **CubemapArray** | Only supported in Forward+ and Mobile, not Compatibility. | ++------------------------+-------------------------+------------------------------------------------------------+ +| **samplerExternalOES** | **ExternalTexture** | Only supported in Compatibility/Android platform. | ++------------------------+-------------------------+------------------------------------------------------------+ + +.. note:: Be careful when setting shader uniforms from GDScript, no error will + be thrown if the type does not match. Your shader will just exhibit + undefined behavior. + +.. warning:: + As with the last note, no error will be thrown if the typing does not match while setting a shader uniform, this unintuitively includes setting a (GDscript) 64 bit int/float into a Godot shader language int/float (32 bit). This may lead to unintentional consequences in cases where high precision is required. + + +Uniform limits +~~~~~~~~~~~~~~ + +There is a limit to the total size of shader uniforms that you can use +in a single shader. On most desktop platforms, this limit is ``65536`` +bytes, or 4096 ``vec4`` uniforms. On mobile platforms, the limit is +typically ``16384`` bytes, or 1024 ``vec4`` uniforms. Vector uniforms +smaller than a ``vec4``, such as ``vec2`` or ``vec3``, are padded to +the size of a ``vec4``. Scalar uniforms such as ``int`` or ``float`` +are not padded, and ``bool`` is padded to the size of an ``int``. + +Arrays count as the total size of their contents. If you need a uniform +array that is larger than this limit, consider packing the data into a +texture instead, since the *contents* of a texture do not count towards +this limit, only the size of the sampler uniform. + Built-in variables ------------------