Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Introdução aos 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 main functions called "processor functions". Processor functions are the entry point for your shader into the program. There are seven different processor functions.

  1. The vertex() function runs over all the vertices in the mesh and sets their positions and some other per-vertex variables. Used in canvas_item shaders and spatial shaders.

  2. The fragment() function runs for every pixel covered by the mesh. It uses values output by the vertex() function, interpolated between the vertices. Used in canvas_item shaders and spatial shaders.

  3. The light() function runs for every pixel and for every light. It takes variables from the fragment() function and from its previous runs. Used in canvas_item shaders and spatial shaders.

  4. The start() function runs for every particle in a particle system once when the particle is first spawned. Used in particles shaders.

  5. The process() function runs for every particle in a particle system for each frame. Used in particles shaders.

  6. The sky() function runs for every pixel in the radiance cubemap when the radiance cubemap needs to be updated, and for every pixel on the current screen. Used in sky shaders.

  7. The fog() function runs for every froxel in the volumetric fog froxel buffer that intersects with the FogVolume. Used by fog shaders.

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.

Nota

Godot also exposes an API for users to write totally custom GLSL shaders. For more information see Using compute shaders.

Tipos de shader

Instead of supplying a general-purpose configuration for all uses (2D, 3D, particles, sky, fog), you must specify the type of shader you're writing. Different types support different render modes, built-in variables, and processing functions.

Em Godot, todos os shaders precisam especificar seu tipo na primeira linha, assim:

shader_type spatial;

Aqui estão os tipos disponíveis:

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.

Cada tipo de shader tem diferentes modos de renderização. Veja a referência para cada tipo de shader para uma lista completa de modos de renderização.

Processador de vértice

A função de processamento vertex() é chamada uma vez para cada vértice em spatial e canvas_item shaders. Para particles shaders, ela é chamada uma vez para cada partícula.

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.

Por padrão, Godot transforma suas informações de vértices para você, o que é necessário para projetar a geometria na tela. Você pode utilizar modos de renderização para transformar os dados você mesmo; veja o Spatial shader doc para um exemplo.

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, canvas_item, and sky shaders.

O uso padrão da função de fragmento é configurar as propriedades do material usadas para calcular a iluminação. Por exemplo, você definiria valores para ROUGHNESS, RIM ou TRANSMISSION, que informariam à função de luz como as luzes respondem a esse fragmento. Isso torna possível controlar um pipeline de sombreamento complexo sem que o usuário precise escrever muito código. Se você não precisa dessa funcionalidade integrada, pode ignorá-la e escrever sua própria função de processamento de luz, e Godot a otimizará. Por exemplo, se você não escrever um valor para RIM, o Godot não calculará a iluminação do aro. Durante a compilação, Godot verifica se RIM é usado; caso contrário, ele corta todo o código correspondente. Portanto, você não desperdiçará cálculos nos efeitos que não usa.

Processador de luz

O processador light() funciona por pixel também, e funciona uma vez para cada luz que afeta o objeto. Ele não funciona se nenhuma luz afetar o objeto. Existe como uma função chamada dentro do processador fragment() e normalmente opera na configuração das propriedades do material dentro da função fragment().

O processador light() funciona de forma diferente em 2D do que em 3D; para uma descrição de como funciona em cada um deles, veja sua documentação, CanvasItem shaders e Shaders espaciais, respectivamente.