Parte: 4 — Gráficos, shaders y rendering moderno · Fuente: Godot Engine 4.x — Screen-reading shaders y Custom post-processing ⏱️ Duración estimada: 65 min · Nivel: Avanzado
Aprender a leer lo que ya está dibujado en pantalla y modificarlo con un shader de post-procesado. Verás cómo funciona hint_screen_texture junto a SCREEN_UV, montarás el patrón estándar de Godot 4 — un ColorRect a pantalla completa dentro de un CanvasLayer encima de todo — y escribirás un shader que aplique un tinte de color y una distorsión de onda a la imagen completa del juego. Esta es la base de bloom, distorsión de calor, viñeta y decenas de efectos.
Al finalizar, el alumno podrá:
hint_screen_texture y SCREEN_UV.CanvasLayer + ColorRect fullscreen para post-proceso.SCREEN_UV con sin y TIME.| # | Tema | Por qué importa |
|---|---|---|
| 1 | Qué es el post-procesado | Efectos globales sobre la imagen final |
| 2 | hint_screen_texture |
Da acceso a lo ya renderizado |
| 3 | SCREEN_UV |
Coordenada de pantalla, no del objeto |
| 4 | ColorRect fullscreen |
El lienzo sobre el que se dibuja el efecto |
| 5 | CanvasLayer encima |
Garantiza que cubra toda la escena |
| 6 | Tinte de color | Ejemplo mínimo de manipular la pantalla |
| 7 | Distorsión por UV | Base de calor, agua, ondas de choque |
hint_screen_texture: hint que expone la textura de la pantalla actual al shader. Clave: se declara con filter_linear_mipmap para muestreo suave.SCREEN_UV: coordenada normalizada (0–1) de la posición del fragmento en la pantalla. Clave: con ella se muestrea la pantalla.ColorRect: nodo 2D rectangular; estirado a pantalla completa es el soporte del shader. Clave: su material lleva el shader de post-proceso.CanvasLayer: capa de dibujo independiente de la cámara. Clave: garantiza que el ColorRect quede por encima de todo.rojo*(1,0.6,0.6) da ambiente de alarma.SCREEN_UV antes de muestrear deforma la imagen. Clave: sin(TIME) da ondulación animada.CanvasLayer; el shader lee lo primero. Clave: por eso el efecto ve el juego completo.Usa Godot 4.x. Sobre cualquier escena jugable (2D o 3D con una escena de fondo visible), añade un CanvasLayer y, dentro, un ColorRect. En el inspector del ColorRect, pon el Layout en Full Rect para que cubra la pantalla, y asígnale un ShaderMaterial. Consulta Screen-reading shaders y Custom post-processing. Lo observable: toda la pantalla se tiñe y ondula como bajo el agua.
Montaremos el setup de post-proceso y un shader con tinte + onda.
Paso 1 — Crear el lienzo. En el árbol de tu escena:
CanvasLayer como hijo de la raíz.ColorRect.ColorRect seleccionado, arriba en la barra de layout elige Full Rect (o pon anchors a Full Rect). Ahora cubre toda la ventana.ShaderMaterial con un shader nuevo.Paso 2 — Leer la pantalla y aplicar un tinte. En el shader del ColorRect:
shader_type canvas_item;
uniform sampler2D screen_tex : hint_screen_texture, filter_linear_mipmap;
uniform vec4 tinte : source_color = vec4(1.0, 0.7, 0.7, 1.0);
uniform float mezcla : hint_range(0.0, 1.0) = 0.5;
void fragment() {
vec3 pantalla = texture(screen_tex, SCREEN_UV).rgb; // lo ya dibujado
vec3 teñido = pantalla * tinte.rgb; // multiplicar tinte
COLOR = vec4(mix(pantalla, teñido, mezcla), 1.0);
}
Ejecuta (F6): toda la escena adquiere un tono rojizo. Sube mezcla a 1.0 y el tinte domina; a 0.0 vuelve al original.
Paso 3 — Añadir la distorsión de onda. Desplaza SCREEN_UV antes de muestrear:
uniform float amplitud : hint_range(0.0, 0.05) = 0.01;
uniform float frecuencia : hint_range(1.0, 40.0) = 12.0;
uniform float velocidad : hint_range(0.0, 8.0) = 3.0;
void fragment() {
vec2 uv = SCREEN_UV;
// Onda vertical dependiente de la posición y del tiempo.
uv.x += sin(uv.y * frecuencia + TIME * velocidad) * amplitud;
vec3 pantalla = texture(screen_tex, uv).rgb;
vec3 teñido = pantalla * tinte.rgb;
COLOR = vec4(mix(pantalla, teñido, mezcla), 1.0);
}
Ahora la pantalla ondula horizontalmente como visto a través de agua o calor. Ajusta amplitud y frecuencia para más o menos deformación.
Paso 4 — Encender/apagar el efecto desde GDScript. Controla la intensidad al vuelo:
extends ColorRect
func activar_submarino(activo: bool) -> void:
var m: float = 1.0 if activo else 0.0
material.set_shader_parameter("mezcla", m)
material.set_shader_parameter("amplitud", 0.015 if activo else 0.0)
Llama activar_submarino(true) al entrar bajo el agua y false al salir. El efecto cubre siempre toda la escena porque el ColorRect está en un CanvasLayer por encima.
mezcla a 0.4.amplitud crezca con sin(TIME) para simular oleaje que sube y baja.dot(pantalla, vec3(0.299,0.587,0.114)).step(0.5, SCREEN_UV.y).frecuencia en el inspector y encuentra el valor que parece "temblor de daño".Crea un post-proceso de "confusión" que combine un tinte morado, una distorsión de onda en X e Y y una ligera reducción de saturación, todo activable con una tecla. El efecto debe cubrir el 100% de la pantalla.
Criterio de aceptación: al pulsar la tecla, toda la imagen del juego se tiñe de morado, ondula en dos ejes y pierde saturación; al soltarla vuelve exactamente al render original; y en ningún momento aparecen zonas de la escena sin afectar (el ColorRect cubre la pantalla completa).
| Síntoma | Causa y arreglo |
|---|---|
| La pantalla sale negra o vacía | El ColorRect no cubre la ventana; ponlo en Full Rect dentro de un CanvasLayer |
| No se lee nada de la escena | Falta hint_screen_texture en el uniform; decláralo con filter_linear_mipmap |
| El efecto no está por encima del juego | El ColorRect no está en un CanvasLayer superior; añádelo y súbelo en el árbol |
| La distorsión se ve pixelada | Filtro incorrecto; usa filter_linear_mipmap en el sampler de pantalla |
| El shader afecta a la UI también | La UI está bajo el mismo CanvasLayer; sepárala en otra capa por encima |
¿Por qué un ColorRect y no la cámara? En Godot 4 el patrón recomendado para post-proceso 2D/simple es un ColorRect fullscreen que lee hint_screen_texture; es sencillo y no requiere viewports extra.
¿SCREEN_UV es lo mismo que UV? No. UV es local al ColorRect; SCREEN_UV es la posición en pantalla, que es lo que necesitas para muestrear el render.
¿Puedo apilar varios efectos? Sí, con varios ColorRect en capas sucesivas, o combinando todo en un solo fragment(). Cada capa lee el resultado de la anterior.
¿Esto funciona en móvil? Sí, pero leer la pantalla tiene coste; agrupa efectos en un shader y evita muestreos múltiples innecesarios.
Clase 095 - Shaders 2D: efectos sobre sprites (disolución y outline)
Clase 097 - Efectos: bloom, vignette, aberración cromática y CRT