diff --git a/tutorials/shaders/shader_reference/shading_language.rst b/tutorials/shaders/shader_reference/shading_language.rst index 87fb02e75..2e26e3666 100644 --- a/tutorials/shaders/shader_reference/shading_language.rst +++ b/tutorials/shaders/shader_reference/shading_language.rst @@ -6,11 +6,13 @@ Shading language Introduction ------------ -Godot uses a shading language similar to GLSL ES 3.0. Most datatypes and functions are supported, -and the few remaining ones will likely be added over time. +Godot uses a shading language similar to GLSL ES 3.0. Most datatypes and +functions are supported, and the few remaining ones will likely be added over +time. -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. +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. Data types ---------- @@ -84,8 +86,9 @@ Most GLSL ES 3.0 datatypes are supported: Casting ~~~~~~~ -Just like GLSL ES 3.0, implicit casting between scalars and vectors of the same size but different type is not allowed. -Casting of types of different size is also not allowed. Conversion must be done explicitly via constructors. +Just like GLSL ES 3.0, implicit casting between scalars and vectors of the same +size but different type is not allowed. Casting of types of different size is +also not allowed. Conversion must be done explicitly via constructors. Example: @@ -95,7 +98,8 @@ Example: float a = 2.0; // valid float a = float(2); // valid -Default integer constants are signed, so casting is always needed to convert to unsigned: +Default integer constants are signed, so casting is always needed to convert to +unsigned: .. code-block:: glsl @@ -106,13 +110,13 @@ Default integer constants are signed, so casting is always needed to convert to Members ~~~~~~~ -Individual scalar members of vector types are accessed via the "x", "y", "z" and "w" members. -Alternatively, using "r", "g", "b" and "a" also works and is equivalent. Use whatever fits -best for your needs. +Individual scalar members of vector types are accessed via the "x", "y", "z" and +"w" members. Alternatively, using "r", "g", "b" and "a" also works and is +equivalent. Use whatever fits best for your needs. -For matrices, use the ``m[row][column]`` indexing syntax to access each scalar, or ``m[idx]`` to access -a vector by row index. For example, for accessing the y position of an object in a mat4 you use -``m[3][1]``. +For matrices, use the ``m[row][column]`` indexing syntax to access each scalar, +or ``m[idx]`` to access a vector by row index. For example, for accessing the y +position of an object in a mat4 you use ``m[3][1]``. Constructing ~~~~~~~~~~~~ @@ -129,9 +133,9 @@ Construction of vector types must always pass: // A single scalar for the whole vector vec4 a = vec4(0.0); -Construction of matrix types requires vectors of the same dimension as the matrix. You can -also build a diagonal matrix using ``matx(float)`` syntax. Accordingly, ``mat4(1.0)`` is -an identity matrix. +Construction of matrix types requires vectors of the same dimension as the +matrix. You can also build a diagonal matrix using ``matx(float)`` syntax. +Accordingly, ``mat4(1.0)`` is an identity matrix. .. code-block:: glsl @@ -139,11 +143,13 @@ an identity matrix. mat3 m3 = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)); mat4 identity = mat4(1.0); -Matrices can also be built from a matrix of another dimension. -There are two rules : -If a larger matrix is constructed from a smaller matrix, the additional rows and columns are -set to the values they would have in an identity matrix. If a smaller matrix is constructed -from a larger matrix, the top, left submatrix of the larger matrix is used. +Matrices can also be built from a matrix of another dimension. There are two +rules: + +1. If a larger matrix is constructed from a smaller matrix, the additional rows +and columns are set to the values they would have in an identity matrix. +2. If a smaller matrix is constructed from a larger matrix, the top, left +submatrix of the larger matrix is used. .. code-block:: glsl @@ -154,8 +160,9 @@ from a larger matrix, the top, left submatrix of the larger matrix is used. Swizzling ~~~~~~~~~ -It is possible to obtain any combination of components in any order, as long as the result -is another vector type (or scalar). This is easier shown than explained: +It is possible to obtain any combination of components in any order, as long as +the result is another vector type (or scalar). This is easier shown than +explained: .. code-block:: glsl @@ -173,7 +180,8 @@ is another vector type (or scalar). This is easier shown than explained: Precision ~~~~~~~~~ -It is possible to add precision modifiers to datatypes; use them for uniforms, variables, arguments and varyings: +It is possible to add precision modifiers to datatypes; use them for uniforms, +variables, arguments and varyings: .. code-block:: glsl @@ -182,9 +190,10 @@ It is possible to add precision modifiers to datatypes; use them for uniforms, v highp vec4 a = vec4(0.0, 1.0, 2.0, 3.0); // high precision, uses full float or integer range (default) -Using lower precision for some operations can speed up the math involved (at the cost of less precision). -This is rarely needed in the vertex processor function (where full precision is needed most of the time), -but is often useful in the fragment processor. +Using lower precision for some operations can speed up the math involved (at the +cost of less precision). This is rarely needed in the vertex processor function +(where full precision is needed most of the time), but is often useful in the +fragment processor. Some architectures (mainly mobile) can benefit significantly from this, but there are downsides such as the additional overhead of conversion between @@ -200,8 +209,9 @@ Arrays are containers for multiple variables of a similar type. Local arrays ~~~~~~~~~~~~ -Local arrays are declared in functions. They can use all of the allowed datatypes, except samplers. -The array declaration follows a C-style syntax: ``[const] + [precision] + typename + identifier + [array size]``. +Local arrays are declared in functions. They can use all of the allowed +datatypes, except samplers. The array declaration follows a C-style syntax: +``[const] + [precision] + typename + identifier + [array size]``. .. code-block:: glsl @@ -241,7 +251,9 @@ To access an array element, use the indexing syntax: COLOR.r = arr[0]; // getter -Arrays also have a built-in function ``.length()`` (not to be confused with the built-in ``length()`` function). It doesn't accept any parameters and will return the array's size. +Arrays also have a built-in function ``.length()`` (not to be confused with the +built-in ``length()`` function). It doesn't accept any parameters and will +return the array's size. .. code-block:: glsl @@ -252,7 +264,12 @@ Arrays also have a built-in function ``.length()`` (not to be confused with the .. note:: - If you use an index below 0 or greater than array size - the shader will crash and break rendering. To prevent this, use ``length()``, ``if``, or ``clamp()`` functions to ensure the index is between 0 and the array's length. Always carefully test and check your code. If you pass a constant expression or a simple number, the editor will check its bounds to prevent this crash. + If you use an index below 0 or greater than array size - the shader will + crash and break rendering. To prevent this, use ``length()``, ``if``, or + ``clamp()`` functions to ensure the index is between 0 and the array's + length. Always carefully test and check your code. If you pass a constant + expression or a simple number, the editor will check its bounds to prevent + this crash. Global arrays ~~~~~~~~~~~~~ @@ -271,12 +288,17 @@ You can declare arrays at global space like: .. note:: - Global arrays have to be declared as global constants, otherwise they can be declared the same as local arrays. + Global arrays have to be declared as global constants, otherwise they can be + declared the same as local arrays. Constants --------- -Use the ``const`` keyword before the variable declaration to make that variable immutable, which means that it cannot be modified. All basic types, except samplers can be declared as constants. Accessing and using a constant value is slightly faster than using a uniform. Constants must be initialized at their declaration. +Use the ``const`` keyword before the variable declaration to make that variable +immutable, which means that it cannot be modified. All basic types, except +samplers can be declared as constants. Accessing and using a constant value is +slightly faster than using a uniform. Constants must be initialized at their +declaration. .. code-block:: glsl @@ -286,7 +308,8 @@ Use the ``const`` keyword before the variable declaration to make that variable a = b; // invalid b = a; // valid -Constants cannot be modified and additionally cannot have hints, but multiple of them (if they have the same type) can be declared in a single expression e.g +Constants cannot be modified and additionally cannot have hints, but multiple of +them (if they have the same type) can be declared in a single expression e.g .. code-block:: glsl @@ -302,8 +325,11 @@ Similar to variables, arrays can also be declared with ``const``. COLOR.r = arr[0]; // valid -Constants can be declared both globally (outside of any function) or locally (inside a function). -Global constants are useful when you want to have access to a value throughout your shader that does not need to be modified. Like uniforms, global constants are shared between all shader stages, but they are not accessible outside of the shader. +Constants can be declared both globally (outside of any function) or locally +(inside a function). Global constants are useful when you want to have access to +a value throughout your shader that does not need to be modified. Like uniforms, +global constants are shared between all shader stages, but they are not +accessible outside of the shader. .. code-block:: glsl @@ -315,7 +341,8 @@ Global constants are useful when you want to have access to a value throughout y Structs ------- -Structs are compound types which can be used for better abstraction of shader code. You can declare them at the global scope like: +Structs are compound types which can be used for better abstraction of shader +code. You can declare them at the global scope like: .. code-block:: glsl @@ -343,7 +370,8 @@ Or use struct constructor for same purpose: PointLight light = PointLight(vec3(0.0), vec3(1.0, 0.0, 0.0), 0.5); -Structs may contain other struct or array, you can also instance them as global constant: +Structs may contain other struct or array, you can also instance them as global +constant: .. code-block:: glsl @@ -382,7 +410,8 @@ You can also pass them to functions: Operators --------- -Godot shading language supports the same set of operators as GLSL ES 3.0. Below is the list of them in precedence order: +Godot shading language supports the same set of operators as GLSL ES 3.0. Below +is the list of them in precedence order: +-------------+------------------------+------------------+ | Precedence | Class | Operator | @@ -427,7 +456,7 @@ Godot Shading language supports the most common types of flow control: } // switch - switch(i) { // signed integer expression + switch (i) { // signed integer expression case -1: break; case 0: @@ -451,12 +480,46 @@ Godot Shading language supports the most common types of flow control: } // do while + // Like `while`, but always runs at least once. do { - } while(true); + } while (true); -Keep in mind that, in modern GPUs, an infinite loop can exist and can freeze your application (including editor). -Godot can't protect you from this, so be careful not to make this mistake! +Keep in mind that, in modern GPUs, an infinite loop can exist and can freeze +your application (including editor). Godot can't protect you from this, so be +careful not to make this mistake! + +Also, when comparing floating-point values against a number, make sure to +compare them against a *range* instead of an exact number. + +A comparison like ``if (value == 0.3)`` may not evaluate to ``true``. +Floating-point math is often approximate and can defy expectations. It can also +behave differently depending on the hardware. + +**Don't** do this. + +.. code-block:: glsl + + float value = 0.1 + 0.2; + + // May not evaluate to `true`! + if (value == 0.3) { + // ... + } + +Instead, always perform a range comparison with an epsilon value. The larger the +floating-point number (and the less precise the floating-point number, the +larger the epsilon value should be. + +.. code-block:: glsl + + const float EPSILON = 0.0001; + if (value >= 0.3 - EPSILON && value <= 0.3 + EPSILON) { + // ... + } + +See `floating-point-gui.de `__ for more +information. .. warning:: @@ -466,12 +529,14 @@ Godot can't protect you from this, so be careful not to make this mistake! Discarding ---------- -Fragment and light functions can use the **discard** keyword. If used, the fragment is discarded and nothing is written. +Fragment and light functions can use the **discard** keyword. If used, the +fragment is discarded and nothing is written. Functions --------- -It is possible to define functions in a Godot shader. They use the following syntax: +It is possible to define functions in a Godot shader. They use the following +syntax: .. code-block:: glsl @@ -486,15 +551,16 @@ It is possible to define functions in a Godot shader. They use the following syn } -You can only use functions that have been defined above (higher in the editor) the function from which you are calling -them. +You can only use functions that have been defined above (higher in the editor) +the function from which you are calling them. Function arguments can have special qualifiers: * **in**: Means the argument is only for reading (default). * **out**: Means the argument is only for writing. * **inout**: Means the argument is fully passed via reference. -* **const**: Means the argument is a constant and cannot be changed, may be combined with **in** qualifier. +* **const**: Means the argument is a constant and cannot be changed, may be + combined with **in** qualifier. Example below: @@ -507,9 +573,9 @@ Example below: Varyings ~~~~~~~~ -To send data from the vertex to the fragment processor function, *varyings* are used. They are set -for every primitive vertex in the *vertex processor*, and the value is interpolated for every -pixel in the fragment processor. +To send data from the vertex to the fragment processor function, *varyings* are +used. They are set for every primitive vertex in the *vertex processor*, and the +value is interpolated for every pixel in the fragment processor. .. code-block:: glsl @@ -543,8 +609,8 @@ Varying can also be an array: Interpolation qualifiers ~~~~~~~~~~~~~~~~~~~~~~~~ -Certain values are interpolated during the shading pipeline. You can modify how these interpolations -are done by using *interpolation qualifiers*. +Certain values are interpolated during the shading pipeline. You can modify how +these interpolations are done by using *interpolation qualifiers*. .. code-block:: glsl @@ -574,9 +640,10 @@ 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. +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. .. note:: Uniform arrays are not implemented yet. @@ -587,17 +654,20 @@ Uniforms can't be written from within the shader. uniform float some_value; -You can set uniforms in the editor in the material. Or you can set them through GDScript: +You can set uniforms in the editor in the material. Or you can set them through +GDScript: :: material.set_shader_param("some_value", some_value) -.. note:: The first argument to ``set_shader_param`` 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:: The first argument to ``set_shader_param`` 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. -Any GLSL type except for *void* can be a uniform. Additionally, Godot provides optional shader hints -to make the compiler understand for what the uniform is used. +Any GLSL type except for *void* can be a uniform. Additionally, Godot provides +optional shader hints to make the compiler understand for what the uniform is +used. .. code-block:: glsl @@ -607,7 +677,9 @@ to make the compiler understand for what the uniform is used. uniform float amount : hint_range(0, 1); uniform vec4 other_color : hint_color = vec4(1.0); -It's important to understand that textures that are supplied as color require hints for proper sRGB->linear conversion (i.e. ``hint_albedo``), as Godot's 3D engine renders in linear color space. +It's important to understand that textures that are supplied as color require +hints for proper sRGB->linear conversion (i.e. ``hint_albedo``), as Godot's 3D +engine renders in linear color space. Full list of hints below: @@ -631,8 +703,9 @@ Full list of hints below: | **sampler2D** | hint_aniso | As flowmap, default to right. | +----------------+------------------------------+-------------------------------------+ -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: +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: +-----------------+-----------+ | GDScript type | GLSL type | @@ -654,8 +727,9 @@ to shaders, Godot converts the type automatically. Below is a table of the corre | **Transform2D** | **mat4** | +-----------------+-----------+ -.. 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. +.. 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. Uniforms can also be assigned default values: @@ -670,10 +744,12 @@ Built-in functions ------------------ A large number of built-in functions are supported, conforming to GLSL ES 3.0. -When vec_type (float), vec_int_type, vec_uint_type, vec_bool_type nomenclature is used, it can be scalar or vector. +When vec_type (float), vec_int_type, vec_uint_type, vec_bool_type nomenclature +is used, it can be scalar or vector. -.. note:: For a list of the functions that are not available in the GLES2 backend, please see the - :ref:`Differences between GLES2 and GLES3 doc `. +.. note:: For a list of the functions that are not available in the GLES2 + backend, please see the :ref:`Differences between GLES2 and GLES3 doc + `. +------------------------------------------------------------------------+---------------------------------------------------------------+ | Function | Description / Return value |