
# Shadertoy



Proyecto minimal para ejecutar fragment shaders tipo Shadertoy usando SDL3 + GLAD + OpenGL 3.3.



![Shadertoy - Gameplay](https://php.sustancia.synology.me/images/shadertoy/shadertoy01.png)



## Características

- **Visualizador de shaders fragment** compatible con formato Shadertoy
- **Contador de FPS** en barra de título
- **Toggle VSync** con tecla F4
- **Cambio de shaders en runtime** con flechas ←/→
- **Sistema de metadata** en shaders (Name/Author automático en título)
- **Sistema de feedback** para shaders que requieren frame anterior (opcional)
- **Soporte de audio** con jail_audio (música de fondo)



## Estructura

- src/ — código fuente C++ (incluye main.cpp)
- shaders/ — shaders fragment (.frag.glsl) que se cargan en runtime
- data/ — recursos (música, texturas, etc.)
- third_party/glad/ — glad.c + headers
- third_party/ — jail_audio y otras dependencias
- CMakeLists.txt — configuración de build
- Makefile — builds de release para Windows/macOS/Linux

  

## Requisitos

- CMake >= 3.16

- Compilador con soporte C++17

- SDL3 development headers and library

- GL loader (GLAD) incluido en third_party/glad o disponible en el sistema

  

Instalación típica:

- Debian/Ubuntu:

sudo apt install build-essential cmake libsdl3-dev

- macOS (Homebrew):

brew install cmake sdl3

  

## Build

    mkdir build
    
    cd build
    
    cmake ..
    
    cmake --build . --config Release

  

## Uso

Ejecutar con un shader específico:

    ./shadertoy shaders/fractal_pyramid.frag.glsl



Ejecutar en fullscreen:

    ./shadertoy -F shaders/seascape.frag.glsl
    # o
    ./shadertoy --fullscreen shaders/seascape.frag.glsl



Si ejecutas desde la raíz del repo:

    ./build/shadertoy shaders/water.glsl



### Atajos de teclado

- **ESC** — Salir de la aplicación
- **F3** — Toggle fullscreen
- **F4** — Toggle VSync (ON/OFF)
- **← / →** — Cambiar al shader anterior/siguiente en la carpeta shaders/

  

## Formato de shader esperado

### Header obligatorio:
```glsl
// Name: Nombre del shader
// Author: Autor
#version 330 core
precision highp float;

out vec4 FragColor;
in vec2 vUV;
uniform vec2 iResolution;
uniform float iTime;
```

### Función mainImage (estilo Shadertoy):
```glsl
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    // Tu código aquí
    // fragCoord está en píxeles
    vec2 uv = fragCoord / iResolution.xy;
    fragColor = vec4(uv, 0.5, 1.0);
}
```

### Wrapper main():
```glsl
void main() {
    vec2 fragCoordPixels = vUV * iResolution;
    vec4 outColor;
    mainImage(outColor, fragCoordPixels);
    FragColor = outColor;
}
```

### Metadata opcional:
- `// Name: Nombre` - Aparece en barra de título
- `// Author: Autor` - Aparece en barra de título
- `// iChannel3: self` - Habilita feedback (frame anterior)

  

## Rutas y ejecución

El ejecutable intenta varias rutas relativas para localizar el shader:

- ruta tal cual pasada en argv

- ./<ruta>

- ../<ruta>

- relativo al directorio del ejecutable

  

Si obtienes "Failed to load fragment shader file", ejecuta desde la carpeta build o pasa la ruta correcta a tu shader.

  

## Compatibilidad con Shadertoy

### Características soportadas:
✅ `iTime` - Tiempo en segundos
✅ `iResolution` - Resolución de ventana (vec2)
✅ `mainImage()` - Función de entrada estándar
✅ Self-feedback - Frame anterior con `// iChannel3: self`

### No soportado actualmente:
❌ `iMouse` - Interacción con ratón
❌ `iChannel0-2` - Texturas externas
❌ Multi-pass completo (BufferA/B/C/D)
❌ `iFrame`, `iTimeDelta`, `iDate`

### Diferencias importantes:
- **`iResolution`**: En Shadertoy es `vec3(width, height, width/height)`, aquí es `vec2(width, height)`
  - Solución: `vec3 r = vec3(iResolution.xy, iResolution.x/iResolution.y);`
- **Inicialización de variables**: OpenGL nativo requiere inicializar variables explícitamente
- **División por valores pequeños**: Puede causar overflow - usar `max(divisor, epsilon)`

### Conversión de shaders de Shadertoy:
1. Copiar función `mainImage()` tal cual
2. Añadir header estándar (ver arriba)
3. Añadir wrapper `main()`
4. Eliminar referencias a `iChannel0-3` si no se usan
5. Adaptar `iResolution` de vec3 a vec2 si es necesario
6. Inicializar variables: `vec3 col = vec3(0.0);` en lugar de `vec3 col;`

  

## Troubleshooting

- SDL_Init devuelve error vacío: asegúrate que SDL3.dll (Windows) está en el mismo directorio que el ejecutable o en PATH.

- Errores de compilación/constantes: verifica que usas SDL3 headers (#include <SDL3/SDL.h>) y no SDL2.

- Shaders que fallan a compilar: revisa glGetShaderInfoLog en la salida; versiones GLSL y funciones incompatibles son la causa habitual.

  

## Licencia y créditos

- Código de ejemplo: libre para uso personal y adaptación.

- Respeta créditos de shaders copiados de Shadertoy/otros autores cuando los reutilices.