2 回答

TA貢獻1869條經驗 獲得超4個贊
背景圖
好的,我創建了一個測試RGBA貼圖,它是2張圖像,其中一張包含RGB(左側),第二張包含alpha通道(右側),因此您可以同時看到它們。粗略地將它們組合以形成單個RGBA紋理。
我對它們都做了一些模糊處理,以便在邊緣上獲得更好的視覺效果。
射線鑄造
因為這應該在GLSL中運行,所以我們需要將射線投射到某個地方。我決定在片段著色器中執行此操作。所以算法是這樣的:
在GL側,著色器需要使用統一的制服這里的鼠標位置是紋理坐標,紋理的最大分辨率和透光強度。
在GL側面繪制四邊形,覆蓋整個屏幕,并帶有背景紋理(o混合)
在頂點著色器上,只需傳遞所需的紋理和片段坐標
在每個片段的片段著色器上:
將射線從鼠標位置投射到實際片段位置(在紋理坐標中)
在光線傳播過程中累積/積分光屬性
如果光強度接近零或達到目標碎片位置,則停止。
頂點著色器
// 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
}

TA貢獻1799條經驗 獲得超6個贊
由于GLSL架構與CPU方法相比存在局限性,因此計算量大為冗余。但是我認為它仍然足夠快,但是我沒有對其進行基準測試。有時間我會嘗試。無論如何,它只是一個QUAD,而沒有任何復雜的計算。最慢的是紋理獲取。您可以通過混合或添加更多的循環(每個燈光一個)來添加更多燈光,將結果匯總在一起。您可以通過擴大dt步驟或使用小分辨率地圖紋理來加快處理速度。我沒有在手機上編碼,因此很難說您需要嘗試..
- 2 回答
- 0 關注
- 658 瀏覽
添加回答
舉報