Spatial shaders

    Built-ins

    Values marked as “in” are read-only. Values marked as “out” are for optional writing and will not necessarily contain sensible values. Values marked as “inout” provide a sensible default value, and can optionally be written to. Samplers are not subjects of writing and they are not marked.

    Global built-ins are available everywhere, including custom functions.

    Vertex built-ins

    Vertex data (, NORMAL, TANGENT, BITANGENT) are presented in local model 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:

    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. 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 to 1).

    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.

    Note

    MODELVIEW_MATRIX combines both the WORLD_MATRIX and INV_CAMERA_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 seperated and INV_CAMERA_MATRIX.

    The default use of a Godot 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, Godot will optimize away the corresponding functionality.

    Below are examples of common variables calculated using the built-ins:

    Note

    A commonly used alternative to WORLD_MATRIX[3].xyz is to use vec3 origin = (WORLD_MATRIX * vec4(0,0,0,1)).xyz. It is more efficient to use WORLD_MATRIX[3].xyz as it avoids the matrix multiplication.

    Note

    Shaders going through the transparent pipeline when ALPHA is written to may exhibit transparency sorting issues. Read the 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 setting render_mode to unshaded. If no light function is written, Godot will use the material properties written to in the fragment function to calculate the lighting for you (subject to the render_mode).

    To write a light function, assign something to or SPECULAR_LIGHT. Assigning nothing means no light is processed.

    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:

    If you want the lights to add together, add the light contribution to DIFFUSE_LIGHT using +=, rather than overwriting it.

    Warning

    In GLES2, lights will always be added together even if you override DIFFUSE_LIGHT using =. This is due to lighting being computed in multiple passes (one for each light), unlike GLES3.

    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.)

    Note

    Shaders going through the transparent pipeline when is written to may exhibit transparency sorting issues. Read the for more information and ways to avoid issues.