Attention: Here be dragons (unstable version)
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Redot.
Checking the stable version of the documentation...
Spatial shaders
Spatial shaders are used for shading 3D objects. They are the most complex type of shader Redot offers. Spatial shaders are highly configurable with different render modes and different rendering options (e.g. Subsurface Scattering, Transmission, Ambient Occlusion, Rim lighting etc). Users can optionally write vertex, fragment, and light processor functions to affect how objects are drawn.
Render modes
For visual examples of these render modes, see Standard Material 3D and ORM Material 3D.
Render mode |
Description |
---|---|
blend_mix |
Mix blend mode (alpha is transparency), default. |
blend_add |
Additive blend mode. |
blend_sub |
Subtractive blend mode. |
blend_mul |
Multiplicative blend mode. |
depth_draw_opaque |
Only draw depth for opaque geometry (not transparent). |
depth_draw_always |
Always draw depth (opaque and transparent). |
depth_draw_never |
Never draw depth. |
depth_prepass_alpha |
Do opaque depth pre-pass for transparent geometry. |
depth_test_disabled |
Disable depth testing. |
sss_mode_skin |
Subsurface Scattering mode for skin. |
cull_back |
Cull back-faces (default). |
cull_front |
Cull front-faces. |
cull_disabled |
Culling disabled (double sided). |
unshaded |
Result is just albedo. No lighting/shading happens in material. |
wireframe |
Geometry draws using lines. |
diffuse_burley |
Burley (Disney PBS) for diffuse (default). |
diffuse_lambert |
Lambert shading for diffuse. |
diffuse_lambert_wrap |
Lambert wrapping (roughness dependent) for diffuse. |
diffuse_toon |
Toon shading for diffuse. |
specular_schlick_ggx |
Schlick-GGX for specular (default). |
specular_toon |
Toon for specular. |
specular_disabled |
Disable specular. |
skip_vertex_transform |
|
world_vertex_coords |
|
ensure_correct_normals |
Use when non-uniform scale is applied to mesh. |
shadows_disabled |
Disable computing shadows in shader. |
ambient_light_disabled |
Disable contribution from ambient light and radiance map. |
shadow_to_opacity |
Lighting modifies the alpha so shadowed areas are opaque and non-shadowed areas are transparent. Useful for overlaying shadows onto a camera feed in AR. |
vertex_lighting |
Use vertex-based lighting. |
particle_trails |
Enables the trails when used on particles geometry. |
alpha_to_coverage |
Alpha antialiasing mode, see here for more. |
alpha_to_coverage_and_one |
Alpha antialiasing mode, see here for more. |
fog_disabled |
Disable receiving depth-based or volumetric fog. Useful for blend_add materials like particles. |
Built-ins
Values marked as in
are read-only. Values marked as out
can optionally be written to and will
not necessarily contain sensible values. Values marked as inout
provide a sensible default
value, and can optionally be written to. Samplers cannot be written to so they are not marked.
Global built-ins
Global built-ins are available everywhere, including custom functions.
Built-in |
Description |
---|---|
in float TIME |
Global time since the engine has started, in seconds. It repeats after every |
in float PI |
A |
in float TAU |
A |
in float E |
An |
in bool OUTPUT_IS_SRGB |
|
in float CLIP_SPACE_FAR |
Clip space far |
Vertex built-ins
Vertex data (VERTEX
, NORMAL
, TANGENT
, BITANGENT
) are presented in model space
(also called local space). If not written to, these values will not be modified and be
passed through as they came.
They can optionally be presented in world space by using the world_vertex_coords
render mode.
Users can disable the built-in modelview transform (projection will still happen later) and do it manually with the following code:
shader_type spatial;
render_mode skip_vertex_transform;
void vertex() {
VERTEX = (MODELVIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
NORMAL = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
BINORMAL = normalize((MODELVIEW_MATRIX * vec4(BINORMAL, 0.0)).xyz);
TANGENT = normalize((MODELVIEW_MATRIX * vec4(TANGENT, 0.0)).xyz);
}
Other built-ins, such as UV
, UV2
, and COLOR
, are also passed through to the fragment()
function if not modified.
Users can override the modelview and projection transforms using the POSITION
built-in. If POSITION
is written
to anywhere in the shader, it will always be used, so the user becomes responsible for ensuring that it always has
an acceptable value. When POSITION
is used, the value from VERTEX
is ignored and projection does not happen.
However, the value passed to the fragment shader still comes from VERTEX
.
For instancing, the INSTANCE_CUSTOM
variable contains the instance custom data. When using particles, this information
is usually:
x: Rotation angle in radians.
y: Phase during lifetime (
0.0
to1.0
).z: Animation frame.
This allows you to easily adjust the shader to a particle system using default particles material. When writing a custom particle shader, this value can be used as desired.
Built-in |
Description |
---|---|
in vec2 VIEWPORT_SIZE |
Size of viewport (in pixels). |
in mat4 VIEW_MATRIX |
World space to view space transform. |
in mat4 INV_VIEW_MATRIX |
View space to world space transform. |
in mat4 MAIN_CAM_INV_VIEW_MATRIX |
View space to world space transform of camera used to draw the current viewport. |
in mat4 INV_PROJECTION_MATRIX |
Clip space to view space transform. |
in vec3 NODE_POSITION_WORLD |
Node position, in world space. |
in vec3 NODE_POSITION_VIEW |
Node position, in view space. |
in vec3 CAMERA_POSITION_WORLD |
Camera position, in world space. |
in vec3 CAMERA_DIRECTION_WORLD |
Camera direction, in world space. |
in uint CAMERA_VISIBLE_LAYERS |
Cull layers of the camera rendering the current pass. |
in int INSTANCE_ID |
Instance ID for instancing. |
in vec4 INSTANCE_CUSTOM |
Instance custom data (for particles, mostly). |
in int VIEW_INDEX |
The view that we are rendering.
|
in int VIEW_MONO_LEFT |
Constant for Mono or left eye, always |
in int VIEW_RIGHT |
Constant for right eye, always |
in vec3 EYE_OFFSET |
Position offset for the eye being rendered. Only applicable for multiview rendering. |
inout vec3 VERTEX |
Vertex position in model space. |
in int VERTEX_ID |
The index of the current vertex in the vertex buffer. |
inout vec3 NORMAL |
Normal in model space. |
inout vec3 TANGENT |
Tangent in model space. |
inout vec3 BINORMAL |
Binormal in model space. |
out vec4 POSITION |
If written to, overrides final vertex position. |
inout vec2 UV |
UV main channel. |
inout vec2 UV2 |
UV secondary channel. |
inout vec4 COLOR |
Color from vertices. |
out float ROUGHNESS |
Roughness for vertex lighting. |
inout float POINT_SIZE |
Point size for point rendering. |
inout mat4 MODELVIEW_MATRIX |
Model/local space to view space transform (use if possible). |
inout mat3 MODELVIEW_NORMAL_MATRIX |
|
in mat4 MODEL_MATRIX |
Model/local space to world space transform. |
in mat3 MODEL_NORMAL_MATRIX |
|
inout mat4 PROJECTION_MATRIX |
View space to clip space transform. |
in uvec4 BONE_INDICES |
|
in vec4 BONE_WEIGHTS |
|
in vec4 CUSTOM0 |
Custom value from vertex primitive. When using extra
UVs, |
in vec4 CUSTOM1 |
Custom value from vertex primitive. When using extra
UVs, |
in vec4 CUSTOM2 |
Custom value from vertex primitive. When using extra
UVs, |
in vec4 CUSTOM3 |
Custom value from vertex primitive. |
Note
MODELVIEW_MATRIX
combines both the MODEL_MATRIX
and VIEW_MATRIX
and is better suited when floating point issues may arise. For example, if the object is very far away from the world origin, you may run into floating point issues when using the separated MODEL_MATRIX
and VIEW_MATRIX
.
Note
INV_VIEW_MATRIX
is the matrix used for rendering the object in that pass, unlike MAIN_CAM_INV_VIEW_MATRIX
, which is the matrix of the camera in the scene. In the shadow pass, INV_VIEW_MATRIX
's view is based on the camera that is located at the position of the light.
Fragment built-ins
The default use of a Redot fragment processor function is to set up the material properties of your object and to let the built-in renderer handle the final shading. However, you are not required to use all these properties, and if you don't write to them, Redot will optimize away the corresponding functionality.
Built-in |
Description |
---|---|
in vec2 VIEWPORT_SIZE |
Size of viewport (in pixels). |
in vec4 FRAGCOORD |
Coordinate of pixel center in screen space. |
in bool FRONT_FACING |
|
in vec3 VIEW |
Normalized vector from fragment position to camera (in view space). This is the same for both perspective and orthogonal cameras. |
in vec2 UV |
UV that comes from the |
in vec2 UV2 |
UV2 that comes from the |
in vec4 COLOR |
COLOR that comes from the |
in vec2 POINT_COORD |
Point coordinate for drawing points with |
in mat4 MODEL_MATRIX |
Model/local space to world space transform. |
in mat3 MODEL_NORMAL_MATRIX |
|
in mat4 VIEW_MATRIX |
World space to view space transform. |
in mat4 INV_VIEW_MATRIX |
View space to world space transform. |
in mat4 PROJECTION_MATRIX |
View space to clip space transform. |
in mat4 INV_PROJECTION_MATRIX |
Clip space to view space transform. |
in vec3 NODE_POSITION_WORLD |
Node position, in world space. |
in vec3 NODE_POSITION_VIEW |
Node position, in view space. |
in vec3 CAMERA_POSITION_WORLD |
Camera position, in world space. |
in vec3 CAMERA_DIRECTION_WORLD |
Camera direction, in world space. |
in uint CAMERA_VISIBLE_LAYERS |
Cull layers of the camera rendering the current pass. |
in vec3 VERTEX |
Vertex position that comes from the |
inout vec3 LIGHT_VERTEX |
A writable version of |
in int VIEW_INDEX |
The view that we are rendering.
|
in int VIEW_MONO_LEFT |
Constant for Mono or left eye, always |
in int VIEW_RIGHT |
Constant for right eye, always |
in vec3 EYE_OFFSET |
Position offset for the eye being rendered. Only applicable for multiview rendering. |
sampler2D SCREEN_TEXTURE |
Removed in Redot 4. Use a |
in vec2 SCREEN_UV |
Screen UV coordinate for current pixel. |
sampler2D DEPTH_TEXTURE |
Removed in Redot 4. Use a |
out float DEPTH |
Custom depth value (range of |
inout vec3 NORMAL |
Normal that comes from the |
inout vec3 TANGENT |
Tangent that comes from the |
inout vec3 BINORMAL |
Binormal that comes from the |
out vec3 NORMAL_MAP |
Set normal here if reading normal from a texture instead of |
out float NORMAL_MAP_DEPTH |
Depth from |
out vec3 ALBEDO |
Albedo (default white). Base color. |
out float ALPHA |
Alpha (range of |
out float ALPHA_SCISSOR_THRESHOLD |
If written to, values below a certain amount of alpha are discarded. |
out float ALPHA_HASH_SCALE |
|
out float ALPHA_ANTIALIASING_EDGE |
|
out vec2 ALPHA_TEXTURE_COORDINATE |
|
out float METALLIC |
Metallic (range of |
out float SPECULAR |
Specular. Defaults to |
out float ROUGHNESS |
Roughness (range of |
out float RIM |
Rim (range of |
out float RIM_TINT |
Rim Tint, range of |
out float CLEARCOAT |
Small added specular blob. If used, Redot calculates Clearcoat. |
out float CLEARCOAT_GLOSS |
Gloss of Clearcoat. If used, Redot calculates Clearcoat. |
out float ANISOTROPY |
For distorting the specular blob according to tangent space. |
out vec2 ANISOTROPY_FLOW |
Distortion direction, use with flowmaps. |
out float SSS_STRENGTH |
Strength of Subsurface Scattering. If used, Subsurface Scattering will be applied to object. |
out vec4 SSS_TRANSMITTANCE_COLOR |
|
out float SSS_TRANSMITTANCE_DEPTH |
|
out float SSS_TRANSMITTANCE_BOOST |
|
inout vec3 BACKLIGHT |
|
out float AO |
Strength of Ambient Occlusion. For use with pre-baked AO. |
out float AO_LIGHT_AFFECT |
How much AO affects lights (range of |
out vec3 EMISSION |
Emission color (can go over |
out vec4 FOG |
If written to, blends final pixel color with |
out vec4 RADIANCE |
If written to, blends environment map radiance with |
out vec4 IRRADIANCE |
If written to, blends environment map irradiance with |
Note
Shaders going through the transparent pipeline when ALPHA
is written to
may exhibit transparency sorting issues. Read the
transparency sorting section in the 3D rendering limitations page
for more information and ways to avoid issues.
Light built-ins
Writing light processor functions is completely optional. You can skip the light()
function by using
the unshaded
render mode. If no light function is written, Redot will use the material properties
written to in the fragment()
function to calculate the lighting for you (subject to the render mode).
The light()
function is called for every light in every pixel. It is called within a loop for each light type.
Below is an example of a custom light()
function using a Lambertian lighting model:
void light() {
DIFFUSE_LIGHT += clamp(dot(NORMAL, LIGHT), 0.0, 1.0) * ATTENUATION * LIGHT_COLOR;
}
If you want the lights to add together, add the light contribution to DIFFUSE_LIGHT
using +=
, rather than overwriting it.
Warning
The light()
function won't be run if the vertex_lighting
render mode is enabled, or if
Rendering > Quality > Shading > Force Vertex Shading
is enabled in the Project Settings. (It's enabled by default on mobile platforms.)
Built-in |
Description |
---|---|
in vec2 VIEWPORT_SIZE |
Size of viewport (in pixels). |
in vec4 FRAGCOORD |
Coordinate of pixel center in screen space.
|
in mat4 MODEL_MATRIX |
Model/local space to world space transform. |
in mat4 INV_VIEW_MATRIX |
View space to world space transform. |
in mat4 VIEW_MATRIX |
World space to view space transform. |
in mat4 PROJECTION_MATRIX |
View space to clip space transform. |
in mat4 INV_PROJECTION_MATRIX |
Clip space to view space transform. |
in vec3 NORMAL |
Normal vector, in view space. |
in vec2 UV |
UV that comes from the |
in vec2 UV2 |
UV2 that comes from the |
in vec3 VIEW |
View vector, in view space. |
in vec3 LIGHT |
Light vector, in view space. |
in vec3 LIGHT_COLOR |
Light color multiplied by
light energy multiplied by
|
in float SPECULAR_AMOUNT |
For OmniLight3D and SpotLight3D,
|
in bool LIGHT_IS_DIRECTIONAL |
|
in float ATTENUATION |
Attenuation based on distance or shadow. |
in vec3 ALBEDO |
Base albedo. |
in vec3 BACKLIGHT |
|
in float METALLIC |
Metallic. |
in float ROUGHNESS |
Roughness. |
out vec3 DIFFUSE_LIGHT |
Diffuse light result. |
out vec3 SPECULAR_LIGHT |
Specular light result. |
out float ALPHA |
Alpha (range of |
Note
Shaders going through the transparent pipeline when ALPHA
is written to
may exhibit transparency sorting issues. Read the
transparency sorting section in the 3D rendering limitations page
for more information and ways to avoid issues.
Transparent materials also cannot cast shadows or appear in
hint_screen_texture
and hint_depth_texture
uniforms. This in turn prevents those
materials from appearing in screen-space reflections or refraction.
SDFGI sharp reflections are not visible on transparent
materials (only rough reflections are visible on transparent materials).