猿问

如何在GLSL中实现2D光线投射光效果

这最初是@sydd 在这里询问的。我对此很好奇,所以我尝试对其进行编码,但是在我回答之前,它已被关闭/删除,所以就在这里。


问题:如何在GLSL中复制/实现这种 2D射线投射照明效果?


效果本身将光线从鼠标位置投射到各个方向,从而累积了背景贴图的alpha和影响像素强度的颜色。


因此输入应为:


鼠标位置

背景RGBA地图纹理


子衿沉夜
浏览 620回答 2
2回答

MMTTMM

背景图好的,我创建了一个测试RGBA贴图,它是2张图像,其中一张包含RGB(左侧),第二张包含alpha通道(右侧),因此您可以同时看到它们。粗略地将它们组合以形成单个RGBA纹理。我对它们都做了一些模糊处理,以便在边缘上获得更好的视觉效果。射线铸造因为这应该在GLSL中运行,所以我们需要将射线投射到某个地方。我决定在片段着色器中执行此操作。所以算法是这样的:在GL侧,着色器需要使用统一的制服这里的鼠标位置是纹理坐标,纹理的最大分辨率和透光强度。在GL侧面绘制四边形,覆盖整个屏幕,并带有背景纹理(o混合)在顶点着色器上,只需传递所需的纹理和片段坐标在每个片段的片段着色器上:将射线从鼠标位置投射到实际片段位置(在纹理坐标中)在光线传播过程中累积/积分光属性如果光强度接近零或达到目标碎片位置,则停止。顶点着色器// Vertex#version 420 corelayout(location=0) in vec2 pos;&nbsp; &nbsp; &nbsp;// glVertex2f <-1,+1>layout(location=8) in vec2 txr;&nbsp; &nbsp; &nbsp;// glTexCoord2f&nbsp; Unit0 <0,1>out smooth vec2 t1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// texture end point <0,1>void main()&nbsp; &nbsp; {&nbsp; &nbsp; t1=txr;&nbsp; &nbsp; gl_Position=vec4(pos,0.0,1.0);&nbsp; &nbsp; }片段着色器// Fragment#version 420 coreuniform float transmit=0.99;// light transmition coeficient <0,1>uniform int txrsiz=512;&nbsp; &nbsp; &nbsp;// max texture size [pixels]uniform sampler2D txrmap;&nbsp; &nbsp;// texture unit for light mapuniform vec2 t0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // texture start point (mouse position) <0,1>in smooth vec2 t1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // texture end point, direction <0,1>out vec4 col;void main()&nbsp; &nbsp; {&nbsp; &nbsp; int i;&nbsp; &nbsp; vec2 t,dt;&nbsp; &nbsp; vec4 c0,c1;&nbsp; &nbsp; dt=normalize(t1-t0)/float(txrsiz);&nbsp; &nbsp; c0=vec4(1.0,1.0,1.0,1.0);&nbsp; &nbsp;// light ray strength&nbsp; &nbsp; t=t0;&nbsp; &nbsp; if (dot(t1-t,dt)>0.0)&nbsp; &nbsp; &nbsp;for (i=0;i<txrsiz;i++)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; c1=texture2D(txrmap,t);&nbsp; &nbsp; &nbsp; &nbsp; c0.rgb*=((c1.a)*(c1.rgb))+((1.0f-c1.a)*transmit);&nbsp; &nbsp; &nbsp; &nbsp; if (dot(t1-t,dt)<=0.000f) break;&nbsp; &nbsp; &nbsp; &nbsp; if (c0.r+c0.g+c0.b<=0.001f) break;&nbsp; &nbsp; &nbsp; &nbsp; t+=dt;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; col=0.90*c0+0.10*texture2D(txrmap,t1);&nbsp; // render with ambient light//&nbsp; col=c0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// render without ambient light&nbsp; &nbsp; }

哈士奇WWW

由于GLSL架构与CPU方法相比存在局限性,因此计算量大为冗余。但是我认为它仍然足够快,但是我没有对其进行基准测试。有时间我会尝试。无论如何,它只是一个QUAD,而没有任何复杂的计算。最慢的是纹理获取。您可以通过混合或添加更多的循环(每个灯光一个)来添加更多灯光,将结果汇总在一起。您可以通过扩大dt步骤或使用小分辨率地图纹理来加快处理速度。我没有在手机上编码,因此很难说您需要尝试..
随时随地看视频慕课网APP
我要回答