背景地图
我创建了一个测试的 RGBA 地图,由两张图片组成,一张包含 RGB(在左侧),第二张包含 alpha 通道(在右侧),因此您可以同时看到它们。当然,它们被合并为单个 RGBA 纹理。
我稍微模糊了它们,以获得更好的边缘视觉效果。
光线投射
由于这应该在 GLSL 中运行,我们需要在某个地方进行光线投射。我决定在 片段着色器 中完成。因此,算法如下:
对于每个片段,在片段着色器中:
顶点着色器
// 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
#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
}
最终结果如下:
动画256色GIF:
GIF中的颜色由于8位截断而略有失真。如果动画停止,请刷新页面或在合适的图形查看器中打开。
dt
步长或使用小分辨率映射纹理来加速该过程。我不在手机上编码,所以很难说你需要自己尝试一下... - Spektre