如何在 GLSL 中实现 2D raycasting 光效 [英] How to implement 2D raycasting light effect in GLSL

查看:22
本文介绍了如何在 GLSL 中实现 2D raycasting 光效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这最初是由@sydd

我对它们进行了一些模糊处理,以获得更好的边缘视觉效果.

  • 光线投射

    因为这应该在 GLSL 中运行,所以我们需要将光线投射到某个地方.我决定在片段着色器中进行.所以算法是这样的:

    1. GL 着色器所需的侧通制服 这里将鼠标位置作为纹理坐标、纹理的最大分辨率和透光强度.
    2. GL侧面绘制四边形覆盖整个屏幕,背景纹理(o混合)
    3. 在顶点着色器上只需传递所需的纹理和片段坐标
    4. 在每个片段的片段着色器上:

      • 将光线从鼠标位置投射到实际片段位置(在纹理坐标中)
      • 在光线传播过程中累积/整合光属性
      • 如果光强度接近零或达到目标片段位置,则停止.

  • 顶点着色器

    //顶点#version 420 核心vec2 pos 中的布局(位置 = 0);//glVertex2f <-1,+1>vec2 txr 中的布局(位置 = 8);//glTexCoord2f Unit0 <0,1>输出平滑 vec2 t1;//纹理终点 <0,1>无效主(){t1=txr;gl_Position=vec4(pos,0.0,1.0);}

    片段着色器

    //片段#version 420 核心均匀浮动传输=0.99;//光传输系数<0,1>统一 int txrsiz=512;//最大纹理大小 [像素]统一的 sampler2D txrmap;//光照贴图的纹理单元统一 vec2 t0;//纹理起点(鼠标位置)<0,1>在平滑 vec2 t1 中;//纹理终点,方向 <0,1>出 vec4 col;无效主(){国际我;vec2 t,dt;vec4 c0,c1;dt=标准化(t1-t0)/浮动(txrsiz);c0=vec4(1.0,1.0,1.0,1.0);//光线强度t=t0;如果(点(t1-t,dt)> 0.0)对于 (i=0;i

    最后的结果:

    动画 256 色 GIF:

    由于 8 位截断,GIF 中的颜色略有失真.此外,如果动画停止刷新页面或在 decend gfx 查看器中打开.

    This was originally asked by @sydd here. I was curious about it so I try to code it but It was closed/deleted before I could answer so here it is.

    Question: How to reproduce/implement this 2D ray casting lighting effect in GLSL?

    The effect itself cast rays from mouse position to every direction, accumulating background map alpha and colors affecting the pixels strength.

    So the input should be:

    • mouse position
    • background RGBA map texture

    解决方案

    1. Background map

      Ok I created a test RGBA map as 2 images one containing RGB (on the left) and second with the alpha channel (on the right) so you can see them both. Of coarse they are combined to form single RGBA texture.

      I blurred them both a bit to obtain better visual effects on the edges.

    2. Ray casting

      As this should run in GLSL we need to cast the rays somewhere. I decided to do it in fragment shader. So the algo is like this:

      1. On GL side pass uniforms needed for shaders Here goes mouse position as texture coordinate, max resolution of texture and light transmition strength.
      2. On GL side draw quad covering whole screen with texture of background (o blending)
      3. On Vertex shader just pass the texture and fragment coordinates needed
      4. On Fragment shader per each fragment:

        • cast ray from mouse position to actual fragment position (in texture coordinates)
        • cumulate/integrate the light properties during the ray travel
        • stop if light strength near zero or target fragment position reached.

    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);
        }
    

    Fragment 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
        }
    

    And Finally the result:

    Animated 256 colors GIF:

    The colors in GIF are slightly distorted due to 8 bit truncation. Also if the animation stops refresh page or open in decend gfx viewer instead.

    这篇关于如何在 GLSL 中实现 2D raycasting 光效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆