Introduction to shaders
Shading language.
Shaders are a special kind of program that runs on Graphics Processing Units (GPUs). They were initially used to shade 3D scenes but can nowadays do much more. You can use them to control how the engine draws geometry and pixels on the screen, allowing you to achieve all sorts of effects.
Modern rendering engines like Godot draw everything with shaders: graphics cards can run thousands of instructions in parallel, leading to incredible rendering speed.
Because of their parallel nature, though, shaders don’t process information the way a typical program does. Shader code runs on each vertex or pixel in isolation. You cannot store data between frames either. As a result, when working with shaders, you need to code and think differently from other programming languages.
for loops:
for x in range(width): for y in range(height): set_color(x, y, some_color)
Your code is already part of a loop in a shader, so the corresponding code would look like this.
void fragment() { COLOR = some_color;}
Note
fragment() function once or more for each pixel it has to draw. More on that below.
Shaders in Godot
Godot provides a shading language based on the popular OpenGL Shading Language (GLSL) but simplified. The engine handles some of the lower-level initialization work for you, making it easier to write complex shaders.
vertex(), fragment(), and light().
vertex()function runs over all the vertices in the mesh and sets their positions and some other per-vertex variables.fragment()function runs for every pixel covered by the mesh. It uses values output by thevertex()function, interpolated between the vertices.light()function runs for every pixel and for every light. It takes variables from thefragment()function and from its previous runs. Warninglight()function won’t run if thevertex_lightingrender 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.Shader types
Instead of supplying a general-purpose configuration for all uses (2D, 3D, particles), you must specify the type of shader you’re writing. Different types support different render modes, built-in variables, and processing functions. In Godot, all shaders need to specify their type in the first line, like so:
Here are the available types:shader_type spatial;
- spatial for 3D rendering.
- canvas_item for 2D rendering.
- particles for particle systems.
Render modes
Shaders have optional render modes you can specify on the second line, after the shader type, like so:shader_type spatial;render_mode unshaded, cull_disabled;
unshadedmode makes the engine skip the built-in light processor function. Each shader type has different render modes. See the reference for each shader type for a complete list of render modes.Processor functions
spatialandcanvas_item, you have access tovertex(),fragment(), andlight(). Forparticles, you only have access tovertex().Vertex processor
vertex()processing function is called once for every vertex inspatialandcanvas_itemshaders. Forparticlesshaders, it is called once for every particle. Each vertex in your world’s geometry has properties like a position and color. The function modifies those values and passes them to the fragment function. You can also use it to send extra data to the fragment function using varyings. Spatial shader doc for an example.Fragment processor
fragment()processing function is used to set up the Godot material parameters per pixel. This code runs on every visible pixel the object or primitive draws. It is only available inspatialandcanvas_itemshaders.ROUGHNESS,RIM, orTRANSMISSION, which would tell the light function how the lights respond to that fragment. This makes it possible to control a complex shading pipeline without the user having to write much code. If you don’t need this built-in functionality, you can ignore it and write your own light processing function, and Godot will optimize it away. For example, if you do not write a value toRIM, Godot will not calculate rim lighting. During compilation, Godot checks to see ifRIMis used; if not, it cuts all the corresponding code out. Therefore, you will not waste calculations on the effects that you do not use.Light processor
light()processor runs per pixel too, and it runs once for every light that affects the object. It does not run if no lights affect the object. It exists as a function called inside thefragment()processor and typically operates on the material properties setup inside thefragment()function.light()processor works differently in 2D than it does in 3D; for a description of how it works in each, see their documentation, CanvasItem shaders and Spatial shaders, respectively.
