2013-03-02 103 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次紋理訪問一樣殺死您的性能。只要你只是在渲染之間綁定紋理(即:你不改變程序或其他狀態),並且你正在觀察良好實踐(儘可能在狀態變化之間渲染合理的渲染),你應該相對確定。