Introduction to shaders¶
Esta página explica o que são shaders e lhe dará uma visão geral de como eles funcionam no Godot. Para uma referência detalhada da linguagem de shading do motor, veja Linguagem de shading.
Shaders são um tipo especial de programa executado em unidades de processamento gráfico (GPUs). Eles foram inicialmente usados para sombrear cenas 3D, mas hoje em dia podem fazer muito mais. Você pode usá-los para controlar como o motor desenha a geometria e os pixels na tela, permitindo obter todos os tipos de efeitos.
Motores de renderização modernos como o Godot desenham tudo com shaders: placas gráficas podem executar milhares de instruções em paralelo, levando a uma incrível velocidade de renderização.
Por causa de sua natureza paralela, porém, os shaders não processam informações da mesma forma que um programa típico faz. O código do shader é executado em cada vértice ou pixel isoladamente. Você também não pode armazenar dados entre quadros. Como resultado, ao trabalhar com shaders, você precisa programar e pensar de forma diferente de outras linguagens de programação.
Suponha que você queira atualizar todos os pixels em uma textura para uma determinada cor. Em GDScript, seu código utilizaria loops for
:
for x in range(width):
for y in range(height):
set_color(x, y, some_color)
Seu código já é parte de um loop em um shader, então o código correspondente ficaria assim.
void fragment() {
COLOR = some_color;
}
Nota
A placa gráfica chama a função fragment()
uma ou mais vezes para cada pixel a ser desenhado. Mais sobre isso abaixo.
Shaders em 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.
In Godot, shaders are made up of three main functions: vertex()
,
fragment()
, and light()
.
The
vertex()
function runs over all the vertices in the mesh and sets their positions and some other per-vertex variables.The
fragment()
function runs for every pixel covered by the mesh. It uses values output by thevertex()
function, interpolated between the vertices.The
light()
function runs for every pixel and for every light. It takes variables from thefragment()
function and from its previous runs.
Aviso
The light()
function won't 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.
Tipos de shader¶
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:
shader_type spatial;
Here are the available types:
spatial for 3D rendering.
canvas_item for 2D rendering.
particles for particle systems.
Modos de renderização¶
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;
Render modes alter the way Godot applies the shader. For example, the
unshaded
mode 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.
Funções de processador¶
Depending on the shader type, you can override different processor functions.
For spatial
and canvas_item
, you have access to vertex()
,
fragment()
, and light()
. For particles
, you only have access to
vertex()
.
Processador de vértice¶
The vertex()
processing function is called once for every vertex in
spatial
and canvas_item
shaders. For particles
shaders, 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.
By default, Godot transforms your vertex information for you, which is necessary to project geometry onto the screen. You can use render modes to transform the data yourself; see the Spatial shader doc for an example.
Processador de fragmentos¶
The 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 in spatial
and canvas_item
shaders.
The standard use of the fragment function is to set up material properties used
to calculate lighting. For example, you would set values for ROUGHNESS
,
RIM
, or TRANSMISSION
, 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 to RIM
, Godot will not calculate rim lighting. During compilation,
Godot checks to see if RIM
is used; if not, it cuts all the corresponding
code out. Therefore, you will not waste calculations on the effects that you do
not use.
Processador de luz¶
The 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 the fragment()
processor and typically
operates on the material properties setup inside the fragment()
function.
The 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.