In this part, we cover some of the main keywords in Godot’s shader language.
This lesson is here to get your feet wet and give you the minimum language knowledge to follow the next chapters. There is a lot more to the shading language that we will progressively explore writing real-world effects.
We recommend you to bookmark and read the Godot shader reference. It explains every keyword and data-type in the language in greater detail.
In Godot, a shader must start with the shader_type
statement. It is mandatory. It determines the type of object on which you intend to use the shader.
shader_type canvas_item;
For more information, see the official documentation:
The render_mode
statement is optional. Each rendering pipeline has special flags that can change how any given shader executes, or how it fits in the underlying GLSL shader. Refer to the shader_type
documentation links above to get a list of supported render modes for each type of shader.
The modes below, cull_front
and unshaded
, respectively discard polygons that are facing the camera and make the object unlit. The first mode is only for 3D geometry, while the second also exists in 2D.
render_mode cull_front, unshaded;
Uniforms are variables exposed to the Inspector or game scripts. They come with optional hints that make them easier to use in the Inspector. For example, the : hint_color
adds a color picker next to the property in the Inspector.
You can access uniforms throughout the shader program.
uniform float line_length;
uniform vec4 line_color : hint_color;
uniform sampler2D line_texture;
Uniforms are to shaders what exported variables are to GDScript classes. They expose some of the program’s parameters to change from the outside. If you want to animate a shader, like, for instance, the tint of the screen in a day-night cycle system, you can do so from GDScript.
You access the material
property of the object with the shader attached to it and call its set_shader_param
method. The syntax is the following:
material.set_shader_param("property_name", value)
Conversely, get_shader_param
lets you read the value of a uniform.
Varyings are variables that allow you to forward data from the Vertex shader to the Fragment shader. They allow you to alter pixels based on calculations in the vertex shader. You can use that for special lighting effects that require vertex normal information, like the x-ray view in Hitman games.
varying vec3 camera_to_object_direction;
The rasterizer interpolates between values assigned to varyings in the vertex.
Imagine you have two vertices on either side of the screen, vertex A and B. You assign a value of 0.0
to a varying for vertex A, and 1.0
for vertex B. For a fragment in the middle of the screen, that variable will have a value of 0.5
.
The vertex()
function is your vertex shader in Godot. If you define it, it runs once for every vertex in the object. The vertex shader sets each vertex’s position and orientation in 3D space and calculates any information the fragment shader needs.
void vertex() { POSITION += NORMAL * growth_length; }
Godot uses the content of this function to complete its built-in shaders.
The fragment()
function runs once for every fragment an object occupies. The fragment shader outputs color information for the final appearance of an object on the screen. In 3D, this includes information used later in the rendering pipeline. For example, metallic and roughness, on top of color.
The fragment function below paints your object black.
void fragment() { COLOR.rgb = vec3(0.0); }
Colors can have four channels: Red, Green, Blue, and Alpha, or RGBA. Each channel is a value between 0.0
and 1.0
, unless you’re dealing with high dynamic range colors. Black corresponds to a value of vec3(0.0, 0.0, 0.0)
, and white to vec3(1.0, 1.0, 1.0)
. The color’s fourth component, alpha, controls its opacity. Here are some examples of colors with transparency:
vec4(1.0, 1.0, 1.0, 0.0)
vec4(1.0, 1.0, 1.0, 0.5)
Built-ins are variables, functions, macros, and constants that Godot exposes to make life easier or contain frequently used information.
Some examples include:
TEXTURE
: the texture currently assigned to a 2D node, like a Sprite
.UV
: coordinates of the fragment on the texture, square of one by one arbitrary unit, which we call U and V. When applying textures to a 3D object, we traditionally unwrap and flatten the mesh on that square to map the texture onto it.COLOR
: RGBA color information for canvas items.ALBEDO
: color information for 3D objects. It only contains the RGB color.