opengl Cómo implementar el efecto de luz de emisión de rayos 2D en GLSL



graphics raycasting (1)

Esto fue originalmente preguntado por @sydd aquí . Tenía curiosidad por eso, así que trato de codificarlo, pero fue cerrado / eliminado antes de que pudiera responder, así que aquí está.

Pregunta: ¿Cómo reproducir / implementar este efecto de iluminación de lanzamiento de rayos 2D en GLSL ?

El efecto en sí emite rayos desde la posición del mouse en todas las direcciones, acumulando mapas de fondo alfa y colores que afectan la fuerza de los píxeles.

Entonces la entrada debería ser:

  • posición del mouse
  • textura de mapa RGBA de fondo

  1. Mapa de fondo

    Ok, creé un mapa RGBA de prueba como 2 imágenes, una que contiene RGB (a la izquierda) y la segunda con el canal alfa (a la derecha) para que pueda ver las dos. De grueso, se combinan para formar una textura RGBA única.

    Los desdibujé un poco para obtener mejores efectos visuales en los bordes.

  2. Ray casting

    Como esto debería ejecutarse en GLSL , necesitamos lanzar los rayos en algún lugar. Decidí hacerlo en fragmento sombreador . Entonces el algo es así:

    1. En el lado GL , se necesitan uniformes para los shaders. Aquí se muestra la posición del mouse como la coordenada de la textura, la resolución máxima de la textura y la intensidad de la transmisión de la luz.
    2. En el lado GL dibuja un cuadrante que cubre toda la pantalla con textura de fondo (o mezcla)
    3. En Vertex shader simplemente pasa las coordenadas de textura y fragmento necesarias
    4. En el sombreador de Fragmentos por cada fragmento:

      • emite rayos desde la posición del mouse hasta la posición real del fragmento (en las coordenadas de la textura)
      • acumular / integrar las propiedades de luz durante el recorrido del rayo
      • detenerse si se alcanza la fuerza de la luz cerca de cero o la posición del fragmento objetivo.

Vertex Shader

// Vertex
#version 420 core
layout(location=0) in vec2 pos;     // glVertex2f <-1,+1>
layout(location=8) in vec2 txr;     // glTexCoord2f  Unit0 <0,1>
out smooth vec2 t1;                 // texture end point <0,1>
void main()
    {
    t1=txr;
    gl_Position=vec4(pos,0.0,1.0);
    }

Fragmento shader

// Fragment
#version 420 core
uniform float transmit=0.99;// light transmition coeficient <0,1>
uniform int txrsiz=512;     // max texture size [pixels]
uniform sampler2D txrmap;   // texture unit for light map
uniform vec2 t0;            // texture start point (mouse position) <0,1>
in smooth vec2 t1;          // texture end point, direction <0,1>
out vec4 col;
void main()
    {
    int i;
    vec2 t,dt;
    vec4 c0,c1;
    dt=normalize(t1-t0)/float(txrsiz);
    c0=vec4(1.0,1.0,1.0,1.0);   // light ray strength
    t=t0;
    if (dot(t1-t,dt)>0.0)
     for (i=0;i<txrsiz;i++)
        {
        c1=texture2D(txrmap,t);
        c0.rgb*=((c1.a)*(c1.rgb))+((1.0f-c1.a)*transmit);
        if (dot(t1-t,dt)<=0.000f) break;
        if (c0.r+c0.g+c0.b<=0.001f) break;
        t+=dt;
        }
    col=0.90*c0+0.10*texture2D(txrmap,t1);  // render with ambient light
//  col=c0;                                 // render without ambient light
    }

Y finalmente el resultado:

Animación de 256 colores GIF:

Los colores en GIF están ligeramente distorsionados debido al truncamiento de 8 bits. Además, si la animación detiene la página de actualización o abre en decend viewer gfx.





raycasting