Up to date

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

Introducción a los shaders

Esta página explica qué son los shaders y te proporcionará una visión general de cómo funcionan en Godot. Para una referencia detallada del lenguaje de sombreado del motor, consulta Lenguaje de shading.

Los shaders son un tipo especial de programa que se ejecuta en las Unidades de Procesamiento Gráfico (GPU). Inicialmente se utilizaban para sombrear escenas 3D, pero en la actualidad pueden hacer mucho más. Puedes utilizarlos para controlar cómo el motor dibuja geometría y píxeles en la pantalla, lo que te permite lograr todo tipo de efectos.

Los motores de renderizado modernos como Godot dibujan todo utilizando shaders: las tarjetas gráficas pueden ejecutar miles de instrucciones en paralelo, lo que lleva a una velocidad de renderizado increíble.

Debido a su naturaleza paralela, los shaders no procesan la información de la misma manera que lo hace un programa típico. El código del shader se ejecuta en cada vértice o píxel de forma aislada. Tampoco puedes almacenar datos entre fotogramas. Como resultado, al trabajar con shaders, necesitas programar y pensar de manera diferente a otros lenguajes de programación.

Supongamos que quieres actualizar todos los píxeles de una textura a un color dado. En GDScript, tu código usaría bucles for de la siguiente manera:

for x in range(width):
  for y in range(height):
    set_color(x, y, some_color)

Tu código ya forma parte de un bucle en un shader, por lo que el código correspondiente se vería así.

void fragment() {
  COLOR = some_color;
}

Nota

La tarjeta gráfica llama a la función fragment() una o más veces por cada píxel que tiene que dibujar. Más sobre eso a continuación.

Shaders en Godot

Godot proporciona un lenguaje de sombreado basado en el popular Lenguaje de Sombreado de OpenGL (GLSL) pero simplificado. El motor se encarga de parte del trabajo de inicialización de bajo nivel, lo que facilita la escritura de shaders complejos.

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.

Advertencia

La función light() no se ejecutará si el modo de renderizado vertex_lighting está habilitado, o si la opción Rendering > Quality > Shading > Force Vertex Shading está habilitada en la Configuración del Proyecto. Por defecto, está habilitada en plataformas móviles.

Nota

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

Tipos de Shaders

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.

En Godot, todos los shaders deben especificar su tipo en la primera línea, de la siguiente manera:

shader_type spatial;

Aqui están los tipos validos:

Modos de renderizado

Los shaders tienen modos de renderizado opcionales que puedes especificar en la segunda línea, después del tipo de shader, de la siguiente manera:

shader_type spatial;
render_mode unshaded, cull_disabled;

Los modos de renderizado alteran la forma en que Godot aplica el shader. Por ejemplo, el modo unshaded hace que el motor omita la función incorporada de procesamiento de luces.

Cada tipo de shader tiene diferentes modos de renderizado. Consulta la referencia de cada tipo de shader para obtener una lista completa de los modos de renderizado disponibles.

Procesador Vertex

La función de procesamiento vertex() se llama una vez por cada vértice en los shaders spatial y canvas_item. Para los shaders de particles, se llama una vez por cada partícula.

Cada vértice en la geometría de tu mundo tiene propiedades como una posición y un color. La función "vertex()" modifica esos valores y los pasa a la función "fragment()". También puedes usarla para enviar datos adicionales a la función "fragment()" utilizando "varyings".

Por defecto, Godot transforma la información de tus vértices por ti, lo cual es necesario para proyectar la geometría en la pantalla. Sin embargo, puedes utilizar modos de renderizado para transformar los datos tú mismo; consulta la documentación de shaders espaciales para ver un ejemplo.

Procesador Fragment

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.

El uso estándar de la función fragment() es configurar las propiedades del material que se utilizan para calcular la iluminación. Por ejemplo, podrías establecer valores para ROUGHNESS, RIM o TRANSMISSION, que le indicarían a la función de luz cómo responder a esa fracción. Esto permite controlar un complejo proceso de sombreado sin que el usuario tenga que escribir mucho código. Si no necesitas esta funcionalidad incorporada, puedes ignorarla y escribir tu propia función de procesamiento de luz, y Godot la optimizará. Por ejemplo, si no escribes un valor en RIM, Godot no calculará la iluminación del borde. Durante la compilación, Godot comprueba si se utiliza RIM; si no es así, eliminará todo el código correspondiente. Por lo tanto, no desperdiciarás cálculos en efectos que no utilices.

Procesador Light

El procesador light() también se ejecuta por píxel y se ejecuta una vez por cada luz que afecta al objeto. No se ejecuta si ninguna luz afecta al objeto. Es una función que se llama dentro del procesador fragment() y generalmente opera en las propiedades del material configuradas dentro del procesador fragment().

El procesador light() funciona de manera diferente en 2D que en 3D; para una descripción de cómo funciona en cada caso, consulta su documentación en Shaders de CanvasItem y Shaders espaciales, respectivamente.