mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-05 22:09:56 +03:00
Document global and per-instance uniforms in Shading language (#6414)
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
@@ -839,6 +839,155 @@ The syntax also supports subgroups (it's not mandatory to declare the base group
|
||||
|
||||
group_uniforms MyGroup.MySubgroup;
|
||||
|
||||
Global uniforms
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Sometimes, you want to modify a parameter in many different shaders at once.
|
||||
With a regular uniform, this takes a lot of work as all these shaders need to be
|
||||
tracked and the uniform needs to be set for each of them. Global uniforms allow
|
||||
you to create and update uniforms that will be available in all shaders, in
|
||||
every shader type (``canvas_item``, ``spatial``, ``particles``, ``sky`` and
|
||||
``fog``).
|
||||
|
||||
Global uniforms are especially useful for environmental effects that affect many
|
||||
objects in a scene, like having foliage bend when the player is nearby, or having
|
||||
objects move with the wind.
|
||||
|
||||
To create a global uniform, open the **Project Settings** then go to the
|
||||
**Shader Globals** tab. Specify a name for the uniform (case-sensitive) and a
|
||||
type, then click **Add** in the top-right corner of the dialog. You can then
|
||||
edit the value assigned to the uniform by clicking the value in the list of
|
||||
uniforms:
|
||||
|
||||
.. figure:: img/shading_language_adding_global_uniforms.webp
|
||||
:align: center
|
||||
:alt: Adding a global uniform in the Shader Globals tab of the Project Settings
|
||||
|
||||
Adding a global uniform in the Shader Globals tab of the Project Settings
|
||||
|
||||
After creating a global uniform, you can use it in a shader as follows:
|
||||
|
||||
::
|
||||
|
||||
shader_type canvas_item;
|
||||
|
||||
global uniform vec4 my_color;
|
||||
|
||||
void fragment() {
|
||||
COLOR = my_color.rgb;
|
||||
}
|
||||
|
||||
Note that the global uniform *must* exist in the Project Settings at the time
|
||||
the shader is saved, or compilation will fail. While you can assign a default
|
||||
value using ``global uniform vec4 my_color = ...`` in the shader code, it will
|
||||
be ignored as the global uniform must always be defined in the Project Settings
|
||||
anyway.
|
||||
|
||||
To change the value of a global uniform at run-time, use the
|
||||
:ref:`RenderingServer.global_shader_parameter_set <class_RenderingServer_method_global_shader_parameter_set>`
|
||||
method in a script:
|
||||
|
||||
::
|
||||
|
||||
RenderingServer.global_shader_parameter_set("my_color", Color(0.3, 0.6, 1.0))
|
||||
|
||||
Assigning global uniform values can be done as many times as desired without
|
||||
impacting performance, as setting data doesn't require synchronization between
|
||||
the CPU and GPU.
|
||||
|
||||
You can also add or remove global uniforms at run-time:
|
||||
|
||||
::
|
||||
|
||||
RenderingServer.global_shader_parameter_add("my_color", RenderingServer.GLOBAL_VAR_TYPE_COLOR, Color(0.3, 0.6, 1.0))
|
||||
RenderingServer.global_shader_parameter_remove("my_color")
|
||||
|
||||
Adding or removing global uniforms at run-time has a performance cost, although
|
||||
it's not as pronounced compared to getting global uniform values from a script
|
||||
(see the warning below).
|
||||
|
||||
.. warning::
|
||||
|
||||
While you *can* query the value of a global uniform at run-time in a script
|
||||
using ``RenderingServer.global_shader_parameter_get("uniform_name")``, this
|
||||
has a large performance penalty as the rendering thread needs to synchronize
|
||||
with the calling thread.
|
||||
|
||||
Therefore, it's not recommended to read global shader uniform values
|
||||
continuously in a script. If you need to read values in a script after
|
||||
setting them, consider creating an :ref:`autoload <doc_singletons_autoload>`
|
||||
where you store the values you need to query at the same time you're setting
|
||||
them as global uniforms.
|
||||
|
||||
.. _doc_shading_language_per_instance_uniforms:
|
||||
|
||||
Per-instance uniforms
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. note::
|
||||
|
||||
Per-instance uniforms are only available in ``spatial`` (3D) shaders.
|
||||
|
||||
Sometimes, you want to modify a parameter on each node using the material. As an
|
||||
example, in a forest full of trees, when you want each tree to have a slightly
|
||||
different color that is editable by hand. Without per-instance uniforms, this
|
||||
requires creating a unique material for each tree (each with a slightly
|
||||
different hue). This makes material management more complex, and also has a
|
||||
performance overhead due to the scene requiring more unique material instances.
|
||||
Vertex colors could also be used here, but they'd require creating unique copies
|
||||
of the mesh for each different color, which also has a performance overhead.
|
||||
|
||||
Per-instance uniforms are set on each GeometryInstance3D, rather than on each
|
||||
Material instance. Take this into account when working with meshes that have
|
||||
multiple materials assigned to them, or MultiMesh setups.
|
||||
|
||||
::
|
||||
|
||||
shader_type spatial;
|
||||
|
||||
// Provide a hint to edit as a color. Optionally, a default value can be provided.
|
||||
// If no default value is provided, the type's default is used (e.g. opaque black for colors).
|
||||
instance uniform vec4 my_color : source_color = vec4(1.0, 0.5, 0.0, 1.0);
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = my_color.rgb;
|
||||
}
|
||||
|
||||
After saving the shader, you can change the per-instance uniform's value using
|
||||
the inspector:
|
||||
|
||||
.. figure:: img/shading_language_per_instance_uniforms_inspector.webp
|
||||
:align: center
|
||||
:alt: Setting a per-instance uniform's value in the GeometryInstance3D section of the inspector
|
||||
|
||||
Setting a per-instance uniform's value in the GeometryInstance3D section of the inspector
|
||||
|
||||
Per-instance uniform values can also be set at run-time using
|
||||
`set_instance_shader_parameter<class_GeometryInstance3D_method_set_instance_shader_parameter>`
|
||||
method on a node that inherits from :ref:`class_GeometryInstance3D`:
|
||||
|
||||
::
|
||||
|
||||
$MeshInstance3D.set_instance_shader_parameter("my_color", Color(0.3, 0.6, 1.0))
|
||||
|
||||
When using per-instance uniforms, there are some restrictions you should be aware of:
|
||||
|
||||
- **Per-instance uniforms do not support textures**, only regular scalar and
|
||||
vector types. As a workaround, you can pass a texture array as a regular
|
||||
uniform, then pass the index of the texture to be drawn using a per-instance
|
||||
uniform.
|
||||
- There is a practical maximum limit of 16 instance uniforms per shader.
|
||||
- If your mesh uses multiple materials, the parameters for the first mesh
|
||||
material found will "win" over the subsequent ones, unless they have the same
|
||||
name, index *and* type. In this case, all parameters are affected correctly.
|
||||
- If you run into the above situation, you can avoid clashes by manually
|
||||
specifying the index (0-15) of the instance uniform by using the
|
||||
``instance_index`` hint:
|
||||
|
||||
::
|
||||
|
||||
instance uniform vec4 my_color : source_color, instance_index(5);
|
||||
|
||||
Built-in variables
|
||||
------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user