Parte: 4 — Gráficos, shaders y rendering moderno · Fuente: Documentación de VisualShader de Godot 4 + Referencia de nodos del editor de shaders ⏱️ Duración estimada: 45 min · Nivel: Avanzado
Dominar el VisualShader de Godot 4: el editor de nodos que genera un shader sin escribir código. Al terminar sabrás cuándo conviene el grafo frente al código, reconocerás los nodos más comunes (entradas, texturas, aritmética, Mix, Fresnel), sabrás exponer uniforms visuales, leerás el código generado para entender la equivalencia con el lenguaje de Godot, y trazarás el paralelo conceptual con Shader Graph de Unity y el material graph de Unreal.
Al finalizar, el alumno podrá:
VisualShader de tipo spatial o canvas_item y conectar nodos hasta una salida.UV, Time), Texture2D, Mix, Vector, Fresnel.| # | Tema | Por qué importa |
|---|---|---|
| 1 | Qué es un VisualShader | Genera el mismo shader que el código, con nodos |
| 2 | Grafo vs código | Cada enfoque gana en distintos contextos de equipo |
| 3 | Nodos de entrada | UV, Time, Normal alimentan el grafo |
| 4 | Nodos de operación | Mix, Add, Multiply, Fresnel construyen el efecto |
| 5 | Uniforms visuales | Exponen parámetros ajustables sin tocar nodos |
| 6 | Nodos de salida | Output define ALBEDO, ALPHA, etc. |
| 7 | Leer el código generado | Confirma qué produce el grafo y ayuda a aprender |
| 8 | Paralelo con Unity/Unreal | El concepto de grafo de materiales es transversal |
uniform en código y aparece en el Inspector.ALBEDO, ALPHA, EMISSION). Clave: sin conexión a él, no se ve nada.Mix (lerp): interpola entre dos valores según un factor. Clave: base de degradados y disoluciones.Fresnel: intensifica el borde según el ángulo de vista. Clave: da brillo de contorno con un solo nodo.Trabajarás dentro del editor de Godot 4, sin salir a un archivo .gdshader. Crea un ShaderMaterial y, en su propiedad Shader, elige New VisualShader. Se abre el panel de grafo en la parte inferior; con clic derecho o el botón Add Node insertas nodos. Ten a mano la lista de nodos disponibles en la documentación de VisualShader de Godot. Para el paralelo conceptual, es útil ojear la documentación de Shader Graph de Unity. No necesitas escribir código salvo para leer el que Godot genera automáticamente.
Reconstruiremos un degradado con disolución primero en código y luego con VisualShader, comparando ambos.
Paso 1 — La versión en código (referencia). Crea un MeshInstance3D con un PlaneMesh y un ShaderMaterial. Como referencia, este es el efecto que buscamos: un degradado vertical sobre las UV que se "disuelve" según un uniform.
shader_type spatial;
uniform float corte : hint_range(0.0, 1.0) = 0.5;
void fragment() {
// Degradado vertical usando la coordenada V.
float grad = UV.y;
// Color base interpolado entre dos tonos.
vec3 color = mix(vec3(0.1, 0.2, 0.8), vec3(0.9, 0.7, 0.1), grad);
ALBEDO = color;
// Disolución dura: descarta píxeles bajo el corte.
if (grad < corte) {
discard;
}
}
Paso 2 — Crear el VisualShader. En un nuevo MeshInstance3D, asigna un ShaderMaterial y en Shader elige New VisualShader de tipo spatial. Se abre el editor de grafo con el nodo Output ya presente.
Paso 3 — El degradado. Añade un nodo de entrada Input → UV (da un vec2). Inserta un nodo VectorDecompose (o Swizzle) para extraer la componente Y: ese float es tu degradado vertical. Conéctalo hacia donde lo necesites.
Paso 4 — La mezcla de color. Añade un nodo Mix (interpolación) con dos entradas de color: un ColorConstant azul y otro amarillo. Usa la Y del UV como factor de la mezcla. La salida del Mix va al puerto Albedo del nodo Output.
Paso 5 — La disolución con uniform visual. Crea un nodo FloatParameter (uniform visual) llamado corte, con rango 0–1. Añade un nodo Comparison / Step que compare la Y del UV contra corte, y lleva el resultado al puerto Alpha Scissor Threshold del Output (o multiplícalo en Alpha activando transparencia). Al mover corte en el Inspector, el plano se recorta como en la versión en código.
Paso 6 — Leer el código generado. Con el VisualShader seleccionado, en el menú del recurso elige mostrar el shader generado (o inspecciona el .tres). Verás algo equivalente a:
// Fragmento generado (simplificado) por el VisualShader:
shader_type spatial;
uniform float corte;
void fragment() {
float grad = UV.y;
vec3 color = mix(vec3(0.1, 0.2, 0.8), vec3(0.9, 0.7, 0.1), grad);
ALBEDO = color;
ALPHA_SCISSOR_THRESHOLD = corte; // recorte por alfa
}
Paso 7 — Controlar el uniform desde código. Como cualquier ShaderMaterial, el uniform visual se ajusta por API:
# Animar el corte de disolución de 0 a 1 a lo largo del tiempo.
var mat: ShaderMaterial = $MeshInstance3D.get_active_material(0)
func _process(delta: float) -> void:
var t: float = fmod(Time.get_ticks_msec() / 1000.0, 1.0)
mat.set_shader_parameter("corte", t)
Resultado observable: dos planos con el mismo degradado; en el del VisualShader mueves el uniform corte (a mano o animado) y el plano se disuelve exactamente igual que su gemelo escrito en código.
ColorConstant del Mix y observa cómo cambia el degradado sin tocar código.FloatParameter para la suavidad del borde usando SmoothStep en vez de Step..gdshader, el shader que generó tu grafo y confirma que se ve igual.Reproduce un mismo efecto de disolución en dos versiones: una escrita en código y otra en VisualShader, ambas con un uniform corte en rango 0–1. Deben verse idénticas al barrer el uniform y ambas deben poder animarse desde GDScript con set_shader_parameter.
Criterio de aceptación: al animar corte de 0 a 1, los dos planos se disuelven de forma indistinguible; entregas una captura de tu grafo VisualShader y el código generado, señalando qué nodo produce cada línea clave.
| Síntoma | Causa y arreglo |
|---|---|
| El grafo no se ve en pantalla | No conectaste nada al nodo Output (Albedo/Alpha) |
| No puedo unir dos puertos | Tipos incompatibles (float vs vec3); añade un nodo de conversión/swizzle |
| El uniform no aparece en el Inspector | Usaste una constante en vez de un *Parameter; cámbialo por un uniform visual |
| La disolución no recorta | Olvidaste enviar el umbral a Alpha Scissor Threshold o activar transparencia |
| El código generado se ve enredado | Es normal: el grafo prioriza corrección sobre legibilidad; léelo por bloques |
| Cambios no se guardan | El VisualShader es un recurso; guarda la escena/recurso tras editarlo |
¿El VisualShader es menos potente que el código? Cubre la mayoría de casos, pero para lógica muy específica el código es más directo. Además existe un nodo de Expression para escribir GLSL dentro del grafo.
¿Cuándo conviene el grafo sobre el código? Cuando iteras visualmente, colaboras con artistas técnicos o quieres ver el resultado de cada nodo. El código gana en efectos complejos y control de versiones limpio.
¿El grafo genera un shader "peor" en rendimiento? No inherentemente: produce código equivalente. El coste depende de qué nodos uses (lookups, branches), igual que en código escrito a mano.
¿Se parece al Shader Graph de Unity o al de Unreal? Conceptualmente sí: nodos de entrada, operaciones y una salida de material. Cambian los nombres y algunos nodos, pero el modelo mental es el mismo.
Clase 105 - Optimización de shaders y coste en GPU
Clase 107 - Capstone Parte 4: set de shaders y post-procesado