2016-11-21 70 views
0

我正在處理會支持8個紋理的紋理/地形splatting GLSL着色器。GLSL着色器:var A中的一半顏色值,var B中的另一半,沒有條件語句

我製作的第一個版本使用RGBA作爲輸入 - 每個通道都是每個紋理的強度。

第二個版本我試圖通過將它們分成兩半來使「頻道」加倍。例如;

  • R0 =上Texture1
  • R64 =半紋理無1
  • R127 =質感十足1
  • R128 =無紋理5
  • R196 =半質地5
  • R254 =完整紋理5

andsoforth。

我已經知道,如果在着色器中的語句是非常糟糕的做法 - 它也覺得做錯了什麼。

事情是,我不知道將每個通道的一半用作完整變量的數學函數。

這裏是片段着色器代碼;

varying vec2 v_vTexcoord; 
varying vec4 v_vColour; 

uniform sampler2D texture; //Texture 

uniform float surfWidth; 
uniform float surfHeight; 

uniform float xpos; 
uniform float ypos; 

void main() 
{ 
    //Setting the main texture position 
    vec2 texpos = (v_vTexcoord*vec2(surfWidth, surfHeight)) +  vec2(xpos, ypos); 

    //Modulo 1 for repeat, devide by 4 because its a 4x4 texture sheet 
    float tpx = mod(texpos.x,1.0)/4.0; 
    float tpy = mod(texpos.y,1.0)/4.0; 

    //Setup terrain "intensities" 
    float t1 = 0.0; 
    float t2 = 0.0; 
    float t3 = 0.0; 
    float t4 = 0.0; 
    float t5 = 0.0; 
    float t6 = 0.0; 
    float t7 = 0.0; 
    float t8 = 0.0; 

    //Load from the surface (splatmap) 
    float btr = (v_vColour * texture2D(gm_BaseTexture,  v_vTexcoord)).r; 
    float btg = (v_vColour * texture2D(gm_BaseTexture, v_vTexcoord)).g; 
    float btb = (v_vColour * texture2D(gm_BaseTexture, v_vTexcoord)).b; 
    float bta = (v_vColour * texture2D(gm_BaseTexture, v_vTexcoord)).a; 

    //Calculating what texture to use (also deviding each channel into  2) 
    if (btr <= 0.5) { 
     t1 = btr*2.0; 
    } else { 
     t5 = (btr-0.5)*2.0; 
    } 

    if (btg <= 0.5) { 
     t2 = btg*2.0; 
    } else { 
     t6 = (btg-0.5)*2.0; 
    } 

    if (btb <= 0.5) { 
     t3 = btb*2.0; 
    } else { 
     t7 = (btb-0.5)*2.0; 
    } 

    if (bta <= 0.5) { 
     t4 = bta*2.0; 
    } else { 
     t8 = (bta-0.5)*2.0; 
    } 

    //Get terrain pixels at proper positions 
    vec4 ter1 = texture2D(texture, vec2(tpx, tpy)); 
    ter1.a = t1; 
    vec4 ter2 = texture2D(texture, vec2(tpx+0.25, tpy)); 
    ter2.a = t2; 
    vec4 ter3 = texture2D(texture, vec2(tpx+0.50, tpy)); 
    ter3.a = t3; 
    vec4 ter4 = texture2D(texture, vec2(tpx+0.75, tpy)); 
    ter4.a = t4; 

    vec4 ter5 = texture2D(texture, vec2(tpx, tpy+0.25)); 
    ter5.a = t5; 
    vec4 ter6 = texture2D(texture, vec2(tpx+0.25, tpy+0.25)); 
    ter6.a = t6; 
    vec4 ter7 = texture2D(texture, vec2(tpx+0.50, tpy+0.25)); 
    ter7.a = t7; 
    vec4 ter8 = texture2D(texture, vec2(tpx+0.75, tpy+0.25)); 
    ter8.a = t8; 

    //Output to screen 
    gl_FragColor = 
    ter1*vec4(t1) + 
    ter2*vec4(t2) + 
    ter3*vec4(t3) + 
    ter4*vec4(t4) + 
    ter5*vec4(t5) + 
    ter6*vec4(t6) + 
    ter7*vec4(t7) + 
    ter8*vec4(t8); 
} 

我敢肯定,我要去給需要這樣的東西clamp()lerp(),但我不能換我的頭周圍..

此外,當紋理重疊,他們得到「光明「(因爲這兩個紋理只是在最後一個語句中添加的......我不知道如何防止這種情況發生,並始終輸出紋理本身的」最大值「(以便它不會」點亮「)。對不起,如果我聽起來很愚蠢,這是我的第一個真正的着色器:)

回答

1

分支機構在現代硬件上沒有那麼差,假設它們跨越多個碎片並可能節省大量工作。寫你的邏輯wihout分支應該是這樣的:

btr *= 2.; 
t1 = fract(min(btr,1.)); 
t5 = max(btr-1.,0.); 

請注意,你的方法,你不能融入被裝在同一個顏色通道(即混合T1和T5。)兩個「潑灑通道」。這將是更簡單(可能更有效),只是採樣另一個splatmap。

至於混合最終輸出,假設你想要線性混合,你會將各個權重除以所有權重之和。

float sum = t1+t2+t3+t4+t5+t6+t7+t8; 
gl_FragColor = ter1*(t1/sum) + ter2*(t2/sum) + ter3*(t3/sum) + ... 
+1

太棒了!非常感謝:)現在我只需要能夠正確地生成splatmap ..但是這會修復我的着色器故障!再次感謝:)您將很快在www.shootmup.com上看到結果 –