# 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 - ./ - ../ - 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 ) 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.