编写sampler2D * 0和sampler2D * 1的最快方法是将多个一起添加? (GLSL / CG)

时间:2014-08-17 09:52:07

标签: unity3d glsl shader gpu cg

我想将许多sampler2D混合到一个着色器中,没有"如果"条件,使用变量m1,m2,m3等于每个sampler2D的0/1表示它是否有效,并将sampler2Ds一次乘以1。

我天真地写了这个函数来合并15个sampler2D' s:

    //float4 blend function is a sampler2D function that "return tex2D (tex,uv);" at 3 different altitudes

    color = blend (_TexTop *m1 + _TexTop2 *m2 + _TexTop3 *m3 + _TexTop4 *m4 + _TexTop5 *m5  ,
    _TexMid *m1 + _TexMid2 *m2 + _TexMid3 *m3 + _TexMid4 *m4 + _TexMid5 *m5 ,
    _TexBot *m1 + _TexBot2 *m2 + _TexBot3 *m3 + _TexBot4 *m4 + _TexBot5 *m5 ,
    _StrataBlendWidth,  _strataAltitudeOffset,  _StrataMidbandWidth, IN.worldPos.y, IN.uv_TexTop);

除了显然不起作用,因为它不可能添加和乘以sampler2Ds。 rarrgh!

重写上述行的最佳方法是,使用0-1整数来打开和关闭sampler2D,如果没有条件和动态分支?

三江源

1 个答案:

答案 0 :(得分:2)

假设我已经理解了你的问题(我不确定),那么就没有办法根据没有分支的统一参数(mx)选择性地采样纹理。

考虑几个事实:

  1. 对制服进行分支并不总是那么昂贵,因为该值在同一个drawcall中是恒定的(我猜这取决于着色器配置文件和硬件,即使避免分支是一个很好的经验法则)。
  2. 如果在最坏的情况下你想要使用你的所有样本(虽然15似乎是一个相当大的数字),那么你可能会考虑总是对它们进行全部采样。
  3. 我不确定这种着色器的实际用例是什么,顺便说一句,根据活动采样器的数量,不同的方法可以编译不同的shader variants

    例如,使用一个采样器编译着色器1的两个变体,另一个用2编译,你可以这样:

    #pragma multi_compile ONE_SAMP TWO_SAMPLE
    
    #ifdef ONE_SAMP
    uniform sampler2D tex1;
    #endif
    #ifdef TWO_SAMP
    uniform sampler2D tex1;
    uniform sampler2D tex2;
    #endif
    
    ...
    
    #ifdef ONE_SAMP
    fixed4 col1 = tex2D(tex1,uv);
    #endif
    #ifdef TWO_SAMP
    fixed4 col1 = tex2D(tex1,uv);
    fixed4 col2 = tex2D(tex2,uv);
    #endif
    

    然后按脚本或使用custom material editor设置有效关键字。


    修改

    在我的回答中,我假设m1,m2值是制服,否则如果它们不存在,那么在没有分支的情况下动态采样纹理真的没办法。