# Shader

> Un widget pintado en la GPU por tu propio código WGSL. Un componente nativo de Pyzed para GUIs de escritorio en Python, con vista previa, ejemplos y su API.

Source: https://albakore.github.io/pyzed/es/library/shader/

:::tip[En pocas palabras]
Una superficie pintada por la tarjeta gráfica, para fondos en movimiento y efectos visuales.
:::

`pz.shader` ejecuta una función que escribes en WGSL, `fn shade(uv, px, size, time) -> vec4<f32>`, para cada píxel del widget, en cada fotograma, en la GPU: fondos animados, plasma, fuego o el barrido de un radar no le cuestan nada a Python. Cada entrada de `uniforms` se convierte en una función WGSL con el mismo nombre, y `mouse()` da la posición del puntero. Sin GPU el widget muestra `fallback`. Ver la [guía de shaders](https://albakore.github.io/pyzed/es/shading/shaders/) y las [demos](https://albakore.github.io/pyzed/es/showcase/).

`pz.shader` · Categoría: [Contenido](https://albakore.github.io/pyzed/es/library/#contenido) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#shader)

**Código:**

```python
pz.shader("""
fn shade(uv: vec2<f32>, px: vec2<f32>, size: vec2<f32>, time: f32) -> vec4<f32> {
    let wave = 0.5 + 0.5 * sin(uv.x * 12.0 + uv.y * 4.0 + time * speed());
    return vec4<f32>(mix(vec3<f32>(0.08, 0.09, 0.2), tint().rgb, wave), 1.0);
}
""", uniforms={"speed": 2.0, "tint": "#c678dd"}, width=640, height=240, time=0.5,
    fallback=pz.Gradient(["#14172f", "#c678dd"], angle=0))
```

:::note[Nuevo]
Este componente se añadió hace poco. Cuéntanos qué tal te funciona en el [gestor de incidencias](https://github.com/albakore/pyzed/issues).
:::

## Cuándo usarlo

- Para fondos animados detrás de paneles de cristal, menús y HUDs.
- Para gráficos y efectos de juegos que serían demasiado lentos de dibujar desde Python en cada fotograma.

## Uso

```python
import pyzed as pz

pz.shader("""
fn shade(uv: vec2<f32>, px: vec2<f32>, size: vec2<f32>, time: f32) -> vec4<f32> {
    let wave = 0.5 + 0.5 * sin(uv.x * 12.0 + uv.y * 4.0 + time * speed());
    return vec4<f32>(mix(vec3<f32>(0.08, 0.09, 0.2), tint().rgb, wave), 1.0);
}
""", uniforms={"speed": 2.0, "tint": "#c678dd"}, width=640, height=240, time=0.5,
    fallback=pz.Gradient(["#14172f", "#c678dd"], angle=0))
```

## Variantes

:::note[Sobre estas capturas]
Cada captura la graba pyzed mismo, fuera de pantalla a 2x, en One Dark o One Light según el tema de este sitio, y recortada al componente para que se vea a su tamaño real. El puntero pasa por encima, pulsa o escribe en él; un componente que no reacciona al puntero recorre algunos temas. Con movimiento reducido ves el primer fotograma. Abre **Código** bajo una captura para ver el fragmento que la dibuja; los nombres libres como `on_save` son tus propios callbacks.
:::

### Uniforms

Cada captura es un fotograma con `time=0.5`; ejecuta el ejemplo para verlo moverse. Sin GPU el widget dibuja su `fallback`.

```python
pz.shader("""
fn shade(uv: vec2<f32>, px: vec2<f32>, size: vec2<f32>, time: f32) -> vec4<f32> {
    let wave = 0.5 + 0.5 * sin(uv.x * 12.0 + uv.y * 4.0 + time * 2.0);
    return vec4<f32>(mix(vec3<f32>(0.08, 0.09, 0.2), tint().rgb, wave), 1.0);
}
""", uniforms={"tint": "#c678dd"}, width=260, height=110, time=0.5,
    fallback=pz.Gradient(["#14172f", "#c678dd"], angle=0))
```

```python
pz.shader("""
fn shade(uv: vec2<f32>, px: vec2<f32>, size: vec2<f32>, time: f32) -> vec4<f32> {
    let wave = 0.5 + 0.5 * sin(uv.x * 12.0 + uv.y * 4.0 + time * 2.0);
    return vec4<f32>(mix(vec3<f32>(0.08, 0.09, 0.2), tint().rgb, wave), 1.0);
}
""", uniforms={"tint": "#56b6c2"}, width=260, height=110, time=0.5,
    fallback=pz.Gradient(["#14172f", "#56b6c2"], angle=0))
```

```python
pz.shader("""
fn shade(uv: vec2<f32>, px: vec2<f32>, size: vec2<f32>, time: f32) -> vec4<f32> {
    let wave = 0.5 + 0.5 * sin(uv.x * 12.0 + uv.y * 4.0 + time * 2.0);
    return vec4<f32>(mix(vec3<f32>(0.08, 0.09, 0.2), tint().rgb, wave), 1.0);
}
""", uniforms={"tint": "#e5c07b"}, width=260, height=110, time=0.5,
    fallback=pz.Gradient(["#14172f", "#e5c07b"], angle=0))
```

## Eventos

Shader no tiene eventos propios: muestra lo que le das. Como todo widget, también tiene los **18 eventos comunes** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), que se conectan con `.on(...)`: mira [Eventos](https://albakore.github.io/pyzed/es/guides/events/) y [Eventos de cada componente](https://albakore.github.io/pyzed/es/library/events/).

## Consejos

:::tip
Los shaders necesitan el renderizador de GPU. Pasa siempre un `fallback` que se vea bien por sí solo: es lo que dibujan el renderizador por software y los equipos sin GPU.
:::

## Propiedades y API

### `pz.shader`

```python
shader(
    code,
    *,
    uniforms=None,
    textures=None,
    width=None,
    height=None,
    animate=True,
    time=None,
    fallback=None,
)
```

Un widget que pinta la GPU con tu función WGSL `fn shade(uv, px, size, time) -> vec4<f32>`, que devuelve el color de cada píxel, o con un grafo de shader hecho de nodos (una ruta `.pzshad` o un `Graph` o `Shader` de [`pyzed.shading`](https://albakore.github.io/pyzed/es/reference/shading/)). Cada entrada de `uniforms` se convierte en una función con su nombre (`{"speed": 2}` -> `speed()`); `mouse()` da la posición del puntero. Sin GPU el widget muestra `fallback`. Lanza `ValueError` con el mensaje del compilador si el código no es válido. Ver la guía de [shaders](https://albakore.github.io/pyzed/es/shading/shaders/).

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `code` | *obligatorio* | Código WGSL que define `shade` (y las funciones auxiliares que quieras), o una ruta `.pzshad`, un `Graph` o un `Shader`. |
| `uniforms` | `None` | Hasta 32 valores con nombre: un número, de 2 a 4 números o un color. Con un `.pzshad`, las variables mutables del shader por nombre. |
| `textures` | `None` | Hasta 8 imágenes, `{nombre: ruta}`: cada una se convierte en `nombre(uv)`, el color de la imagen en `uv`. |
| `width` | `None` | Ancho (`"fill"` por defecto). |
| `height` | `None` | Alto (`"fill"` por defecto). |
| `animate` | `True` | Redibuja en cada frame para que avance `time` (`True`). |
| `time` | `None` | Un `time` fijo en segundos, para un fotograma quieto. |
| `fallback` | `None` | Color o degradado que se muestra sin GPU. |

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/widgets/#shader)

## Relacionados

- [Efectos](https://albakore.github.io/pyzed/es/library/effects/): Glow, bloom, glass y opacidad como propiedades de estilo.
- [Lienzo](https://albakore.github.io/pyzed/es/library/canvas/): Dibujo 2D con formas, trazos, texto y eventos de ratón.
- [Animación](https://albakore.github.io/pyzed/es/library/animation/): Presets, keyframes y transiciones para cualquier widget.
