Comprensión del Renderizado Raymarching en WebGL 2.0
Profundiza en la tecnología Raymarching de WebGL 2.0, aprende a usar campos de distancia con signo SDF para renderizado volumétrico en tiempo real y descubre cómo esta técnica lleva la GPU al límite.

Una inmersión profunda en raymarching WebGL 2.0, SDFs y renderizado volumétrico en tiempo real
WebGL 2.0 desbloquea un poderoso conjunto de características de GPU, permitiendo técnicas avanzadas de renderizado que tradicionalmente requerían APIs nativas. Entre estas, el raymarching se destaca como uno de los métodos más expresivos y matemáticamente elegantes para renderizar escenas complejas con geometría mínima.
Este artículo explora los conceptos fundamentales detrás del raymarching WebGL 2.0, explica cómo los Campos de Distancia con Signo (SDFs) permiten renderizado eficiente y muestra cómo esta técnica puede extraer un rendimiento sorprendente de la GPU.
1. ¿Qué es Raymarching?
Raymarching es un método de renderizado donde, en lugar de proyectar geometría en la pantalla, disparamos un rayo desde la cámara por píxel, lo movemos paso a paso a través de una escena virtual y evaluamos distancias hasta que el rayo golpea una superficie o alcanza un rango máximo.
1.1 Cómo Funciona el Raymarching (Diagrama Visual)
Cámara
|
| rayo
v
+--------------------------------- Píxel de Pantalla
|
| paso de marcha 1 (distancia d1)
|
|---------> paso de marcha 2 (distancia d2)
|
|-----------------------> paso de marcha 3 ...
|
Superficie alcanzada cuando distancia < ε
Raymarching es esencialmente un bucle:
for (int i = 0; i < MAX_STEPS; i++) {
float dist = sdf(currentPos);
if (dist < EPSILON) hitSurface();
currentPos += rayDir * dist;
}
El ingrediente mágico es la función SDF que pasamos.
2. ¿Qué son los Campos de Distancia con Signo (SDFs)?
Un Campo de Distancia con Signo es una función que devuelve:
> 0 distancia fuera del objeto
= 0 exactamente en la superficie
< 0 distancia dentro del objeto
2.1 Diagrama SDF
fuera
+------------+
| d = 0.5 |
| |
dentro | SDF | superficie d = 0
d < 0 | |
| d = -0.3 |
+------------+
2.2 Ejemplo: SDF de Esfera
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
Al combinar estas formas básicas con operaciones booleanas (unión, sustracción, intersección), puedes construir escenas complejas sin ninguna geometría tradicional.
3. ¿Por qué usar Raymarching SDF en WebGL 2.0?
3.1 Beneficios
No se necesitan buffers de vértices o mallas Todo se calcula matemáticamente en el fragment shader.
Detalle geométrico infinito Los SDFs definen superficies suaves y continuas.
Objetos dinámicos y deformables Anima fácilmente formas con matemáticas.
Escenas compactas Una escena 3D completa puede definirse usando solo unas pocas líneas de GLSL.
3.2 Características de WebGL 2.0 que lo hacen posible
- Floats de alta precisión
- Soporte completo de shaders GLSL ES 3.0
- UBOs (buffers uniformes)
- Texturas float
- Bucles y ramificaciones más flexibles
Esto permite raymarching estable y de alto rendimiento que era difícil en WebGL 1.0.
4. Construyendo un Raymarcher WebGL 2.0 Paso a Paso
4.1 Configuración del Rayo de la Escena
Calcula un rayo para cada píxel:
vec3 rayOrigin = cameraPos;
vec3 rayDir = normalize(uv.x * camRight + uv.y * camUp + camForward);
4.2 El Bucle de Raymarch
float marchRay(vec3 ro, vec3 rd) {
float totalDist = 0.0;
for (int i = 0; i < MAX_STEPS; i++) {
vec3 p = ro + rd * totalDist;
float d = map(p); // tu función SDF
if (d < EPSILON) break; // impacto
if (totalDist > MAX_DISTANCE) break; // fallo
totalDist += d;
}
return totalDist;
}
4.3 Definiendo la Escena SDF
float map(vec3 p) {
float s = sdSphere(p, 1.0);
float box = sdBox(p - vec3(2.0, 0.0, 0.0), vec3(0.7));
return min(s, box); // unión
}
4.4 Cálculo de la Normal
Usando aproximación de gradiente:
vec3 calcNormal(vec3 p) {
const vec2 e = vec2(0.001, 0.0);
return normalize(vec3(
map(p + e.xyy) - map(p - e.xyy),
map(p + e.yxy) - map(p - e.yxy),
map(p + e.yyx) - map(p - e.yyx)
));
}
4.5 Modelo de Iluminación
Sombreado difuso simple:
float diffuse = max(dot(normal, lightDir), 0.0);
5. Renderizando Volúmenes (Niebla, Nubes, Humo)
Raymarching SDF puede extenderse a renderizado volumétrico, donde cada paso contribuye color y densidad en lugar de detenerse en una superficie.
5.1 Diagrama de Volumen
Rayo →
[baja densidad] [media] [alta densidad] [opaco]
+--------+---------+---------+-------+
muestra1 muestra2 muestra3 muestra4
5.2 Modelo de Acumulación de Volumen
vec3 color = vec3(0);
float absorption = 1.0;
for (int i = 0; i < STEPS; i++) {
float density = computeDensity(p);
vec3 sampleColor = density * vec3(0.6, 0.7, 1.0);
color += sampleColor * absorption;
absorption *= (1.0 - density * 0.1);
p += rd * STEP_SIZE;
}
Raymarching de volúmenes es más costoso, pero las mejoras de rendimiento de WebGL 2.0 (especialmente en GPUs móviles) hacen viables nubes, niebla y nebulosas en tiempo real.
6. Técnicas de Optimización de Rendimiento
Raymarching puede ser pesado, por lo que las optimizaciones son esenciales.
6.1 Técnicas Clave
Culling de Distancia Salta grandes áreas vacías confiando en distancias SDF precisas.
Volúmenes Delimitadores Prueba si el rayo incluso entra en la región donde existen los SDFs.
Tamaño de Paso Adaptativo Usa pasos más pequeños cerca de superficies, pasos más grandes en espacio abierto.
Salida Temprana Deja de marchar tan pronto como se golpea la superficie.
Reducir MAX_STEPS Los valores típicos oscilan entre 64–128 para renderizado en tiempo real.
Usa uniforms y buffers de WebGL 2.0 eficientemente Mueve valores que no cambian fuera de los bucles.
7. Estructura de Código para un Proyecto WebGL 2.0
Ejemplo de diseño de directorio:
shader/
raymarch.vert
raymarch.frag
src/
webgl2-context.js
camera.js
renderer.js
index.html
Secciones típicas de fragment shader:
// 1. Configuración de Cámara/Rayo
// 2. Definiciones SDF
// 3. Funciones de Material e Iluminación
// 4. Bucle de Raymarch
// 5. Salida de Color Final
8. ¿Cuándo Deberías Usar Raymarching?
Raymarching se destaca cuando quieres:
- Formas suaves infinitas
- Fractales
- Escenas de ciencia ficción
- Sombras suaves de distancia con signo
- Geometría procedural
- Efectos volumétricos (nubes, niebla, rayos de dios)
Evita raymarching cuando necesites:
- Muchas mallas complejas detalladas
- Personajes realistas con skinning
- Escenas dinámicas grandes con miles de objetos
Raymarching es mejor para mundos procedurales y efectos visuales estilizados.
9. Conclusión
El raymarching WebGL 2.0 lleva renderizado avanzado en tiempo real al navegador usando nada más que matemáticas y GLSL. Con SDFs, puedes crear escenas 3D complejas sin un solo buffer de vértices. Aunque la técnica es computacionalmente intensiva, la optimización cuidadosa permite visuales expresivos que rivalizan con aplicaciones GPU nativas.
Raymarching representa una intersección única de matemáticas, arte y programación GPU, convirtiéndolo en una de las técnicas más emocionantes para explorar en el desarrollo WebGL moderno.
Cómo se relaciona esto con el Volume Shader BM Test
Has leído la teoría — ahora el puente práctico hacia la herramienta. Así se aplica todo lo anterior al Volume Shader BM Test.
Por qué esta prueba es más dura que un demo 3D normal
Un demo WebGL típico dibuja unos pocos miles de polígonos. Este benchmark pide a la GPU correr un loop de raymarching por píxel — a menudo más de 1.000 iteraciones cada uno — sin geometría que sirva de atajo. GPUs de gama media que rinden 60 FPS en juegos caen frecuentemente por debajo de 30 FPS en Heavy.
Por qué los FPS caen en móviles
Los móviles aplican throttling agresivo en cuanto el SoC se calienta. Los primeros 10 segundos parecen geniales, luego baja el clock. Conecta el dispositivo a la corriente, ejecuta en Light o Medium y compara por estabilidad, no por pico de FPS. Mira la guía de test GPU móvil.
Por qué la primera ejecución es más lenta (compilación de shader)
En la primera carga el navegador compila GLSL a binario del driver, lo que en algunos drivers tarda cientos de milisegundos y aparece como un tirón al principio. Descarta la primera ejecución y usa la segunda.
Cómo comparar resultados de forma justa
Mismo modo, misma pestaña en primer plano, misma fuente de energía. Light, Medium y Heavy no son comparables directamente porque son cargas distintas. Consulta la guía de FPS.
Qué hacer si el navegador usa la GPU integrada
En portátiles con iGPU y dGPU, Chrome / Edge suelen optar por la integrada para ahorrar batería. Abre chrome://gpu y revisa GL_RENDERER. Si muestra tu iGPU, fuerza el navegador a la GPU dedicada en los ajustes gráficos del SO. La guía de arreglo del lag lo detalla paso a paso.
Prueba el test
Ya tienes la teoría. Ejecuta el benchmark real — menos de un minuto.
Iniciar Volume Shader BM Test →