Ir al contenido

Un efecto de shader desde la vista de shader

Un shader es un programa diminuto que la tarjeta gráfica ejecuta para cada píxel, en cada fotograma: así dibujan los videojuegos anillos luminosos, nubes y fuego sin ir lentos. En Pyzed no tienes que escribir ese programa. Conectas nodos en la vista de shader (como los visual shaders de Godot o el editor de materiales de Unreal) y el diseñador los convierte en código de GPU por ti.

Objetivo Tiempo Nivel Necesitas
Un anillo de neón que late detrás de una tarjeta de bienvenida 25 minutos Intermedio · poco código Tu primera ventana
  • Crear un shader desde una plantilla y moverte por las pestañas Grafo, Vista previa y WGSL.
  • Cambiar la entrada de un nodo, conectar un nodo nuevo y leer la vista previa en cada nodo.
  • Usar variables: valores que tu código Python cambia mientras el shader corre.
  • Dibujar el shader en un formulario con el control Shader y cambiar sus variables desde un botón.
Una tarjeta de bienvenida sobre un anillo cian luminoso
El formulario terminado: el brillo es un shader hecho de nodos; la tarjeta y los botones son controles normales.
  1. Crea el shader. Ctrl+N → Shader, llámalo glow, elige la plantilla Anillo luminoso (Glow ring) y pulsa Crear shader.

    El diálogo de nuevo shader con sus plantillas
    Plantillas: En blanco, Plasma, Nubes, Anillo luminoso, Celdas y Pantalla retro.
  2. Echa un vistazo. La pestaña Grafo muestra los nodos, de izquierda a derecha: Time y las variables alimentan algunas operaciones, una forma Ring da la distancia a un anillo, Glow la convierte en luz y Output es el color final. Cada nodo dibuja una pequeña vista previa de lo que produce, así que puedes seguir la imagen mientras se construye.

    La vista de shader: barra lateral de nodos, el grafo con vistas previas y la salida
    La vista de shader: los nodos en la barra lateral, el grafo en el centro y el resultado en la ventana Output.
  3. Cambia un valor. Las entradas que no están conectadas muestran su valor en el propio nodo. En el nodo Glow cambia radius de 0.12 a 0.3: el brillo crece, y la vista previa de cada nodo posterior se actualiza al instante. (El radio del anillo está conectado: viene de las operaciones del pulso, que es lo que lo hace respirar.)

  4. Conecta un nodo nuevo. Cerca del final, un nodo Multiply mezcla la variable color con el brillo y alimenta al nodo RGBA. Desde la barra lateral Shading arrastra un nodo Hue shift (categoría Color) junto a ellos. Conecta el resultado de Multiply a su entrada rgb y su salida rgb al rgb de RGBA, y luego conecta Time a shift: el anillo ahora recorre todos los colores. Pulsa Ctrl+Z para volver atrás.

  5. Conoce las variables. La Estructura lista las variables del shader: color (el color del neón) y pulse (latidos por segundo). Son mutables: tu app puede cambiarlas en cada fotograma sin coste. La pestaña Vista previa tiene un deslizador para cada una.

    La pestaña Vista previa con un deslizador por variable
    Vista previa: el shader terminado, en grande, con un deslizador por variable.
  6. Guarda (Ctrl+S). El shader es el archivo glow.pzshad. Pulsa F5 para verlo llenar una ventana propia.

  7. Ponlo detrás de un formulario. Crea un formulario welcome (560 × 380). Desde Presentación (Display) en las Herramientas arrastra un control Shader, haz que cubra todo el formulario y ánclalo por los cuatro lados; llámalo backdrop y pon en su Archivo de shader glow.pzshad. Luego añade una Tarjeta en el centro (sin anclajes, para que quede centrada) con un título, una etiqueta llamada hint y dos botones, faster y color. Da a la tarjeta un fondo translúcido en su sección Estilo (#0f172acc) para que se vea el brillo a través.

  8. Contrólalo desde Python. La propiedad variables del control es un dict con las variables del shader. Haz doble clic en faster y color:

    def faster_click(form, event):
    variables = dict(form.backdrop.variables)
    variables["pulse"] = variables.get("pulse", 2.0) + 1.5
    form.backdrop.variables = variables
    def color_click(form, event):
    variables = dict(form.backdrop.variables)
    variables["color"] = "#a78bfa"
    form.backdrop.variables = variables
  9. Ejecuta el formulario (F5) y pulsa los botones.

examples/tutorial/designer/welcome.py
"""Event handlers for the welcome form (tutorial: A shader behind a form).
pyzed run examples/tutorial/designer/welcome.pzform
``backdrop`` is a Shader control that draws ``glow.pzshad``, a shader made of nodes in the
Shader view. Its ``variables`` property sets the shader's variables by name.
"""
from pathlib import Path
COLORS = ["#22d3ee", "#a78bfa", "#f472b6", "#fbbf24"]
def form_load(form, event):
"""Runs once when welcome opens: point the Shader control at the file next to this one.
(A relative path in the Shader file property is read from the folder you run the app
from; building it from ``__file__`` works from anywhere.)
"""
form.backdrop.file = str(Path(__file__).with_name("glow.pzshad"))
def faster_click(form, event):
"""Runs when faster is clicked: more pulses per second, back to 1 after 8."""
variables = dict(form.backdrop.variables)
pulse = variables.get("pulse", 2.0)
variables["pulse"] = 1.0 if pulse >= 8 else pulse + 1.5
form.backdrop.variables = variables
form.hint.text = f"{variables['pulse']:.1f} pulses per second"
def color_click(form, event):
"""Runs when color is clicked: the next neon color."""
variables = dict(form.backdrop.variables)
current = variables.get("color", COLORS[0])
variables["color"] = COLORS[(COLORS.index(current) + 1) % len(COLORS)] if current in COLORS else COLORS[1]
form.backdrop.variables = variables

El mismo shader en Python puro, sin el diseñador, es un widget:

pz.stack([
pz.shader("glow.pzshad", uniforms={"pulse": 4, "color": "#a78bfa"}, width="fill", height="fill"),
card,
])
Windows, macOS y Linux
uv run --with pyzed-ui pyzed run examples/tutorial/designer/welcome.pzform
Cada nodo muestra su vista previa, así que ves cada cambio en cuanto lo conectas.
Control Evento Handler
El formulario load form_load: apunta el control Shader a glow.pzshad.
faster (Botón) click faster_click: cambia la variable pulse.
color (Botón) click color_click: el siguiente color neón.
def color_right_click(form, event): # todo control tiene right_click: vuelve al primer color
variables = dict(form.backdrop.variables)
variables["color"] = COLORS[0]
form.backdrop.variables = variables
def backdrop_mouse_enter(form, event): # el control Shader también tiene los eventos del ratón
form.hint.text = "Aparta el puntero para calmarlo"
def backdrop_mouse_leave(form, event):
form.hint.text = ""