GLSL着色器:var A中的一半颜色值,var B中的另一半,没有条件语句

问题描述:

我正在处理会支持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(),但我不能换我的头周围..

此外,当纹理重叠,他们得到“光明“(因为这两个纹理只是在最后一个语句中添加的......我不知道如何防止这种情况发生,并始终输出纹理本身的”最大值“(以便它不会”点亮“)。对不起,如果我听起来很愚蠢,这是我的第一个真正的着色器:)

分支机构在现代硬件上没有那么差,假设它们跨越多个碎片并可能节省大量工作。写你的逻辑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上看到结果 –