2013-03-02 106 views
2

难道是更快的WebGL来呈现多重纹理一通,如:渲染多重纹理在一个着色器通道

varying float materialIndex; 
varying vec2 textureCoord; 

uniform sampler2D textureSampler1; 
uniform sampler2D textureSampler2; 
uniform sampler2D textureSampler3; 
uniform sampler2D textureSampler4; 

vec4 getMaterial(float materialId, textureCoord) { 
    vec4 color; 

    if (materialId == 1.0) 
    { 
     color = texture2D(textureSampler1, textureCoord); 
    } 
    else if (materialId == 2.0) 
    { 
     color = texture2D(textureSampler2, textureCoord); 
    } 
    else if (materialId == 3.0) 
    { 
     color = texture2D(textureSampler3, textureCoord); 
    } 
    else 
    { 
     color = texture2D(textureSampler4, textureCoord); 
    } 

    return color; 
} 

void main()    
{     
    vec4 color = getMaterial(materialIndex, textureCoord); 
    gl_FragColor = color;   
} 

因为这将节省的CPU必须发送到GPU的指令四分之一,除了顶点着色器必须传递的额外信息之外,在大多数情况下,它不会比4倍的程序调用更快,我已经读过,即使在opengl中,最大的性能影响也是迄今为止的CPU,而我打赌这对Webgl来说更是如此。或者这可能会更快?

uniform float materialIndex; 
varying vec2 textureCoord; 

uniform sampler2D textureSampler1; 
uniform sampler2D textureSampler2; 
uniform sampler2D textureSampler3; 
uniform sampler2D textureSampler4; 


void main()    
{     
    vec4 color = getMaterial(materialIndex, textureCoord); 
    gl_FragColor = color;   
} 

或更改的功能性制服一样糟糕的只是加载一个新的着色器相对于调用CPU必须做多少?

回答

2

配料很重要,是的。但它不是重要。特别是当面临某些硬件可能从全部四种纹理进行采样的可能性时,无论如何。

在各种情况下,编译器不知道该值如何变化。因此,它会假定任何片段都可以获得任何价值。所以它必须为一切做一个运行时分支。由于条件分支的成本,编译器通常会尝试通过简单地执行所有可用路径并使用非分支逻辑计算最终结果来避免连续执行4个条件分支。

由于某些较旧的硬件在功能上无法对重要指令进行条件分支,因此您的统一案例并不安全。所以他们别无选择,只能在每次更换制服时重新编译着色器(而且这并不夸张;旧版硬件上的NVIDIA编译器实际上是这样做的),或者进行全部4次纹理访问。

哦,另一件事:当在非均匀控制流程中(如在有条件执行的块中),texture2D函数变得不确定。现在,它可能不会伤害你,因为你如何使用它。但一般来说,您需要使用明确的渐变或从条件块中删除纹理访问函数。我记得,WebGL没有渐变纹理功能。

总之,只需更改纹理并再次渲染即可。即使在JavaScript中,这也不会像可能进行4次纹理访问一样杀死您的性能。只要你只是在渲染之间绑定纹理(即:你不改变程序或其他状态),并且你正在观察良好实践(尽可能在状态变化之间渲染合理的渲染),你应该相对确定。