2013-05-13 70 views
1

我想在不使用布爾操作(聯合,差異等)的情況下剪切WebGLfragment shaders/vertex shaders)中的對象(一個框)。如何使用WebGL着色器剪切對象?

我想使用着色器來隱藏對象的某些部分(所以它不是真正的「真正的切割」,因爲它只是隱藏對象)。

編輯

+0

我已回覆您的修改。 – 2013-05-25 14:26:23

回答

3

首先,確保頂點着色器經過對片段着色器在世界空間中的位置(或者說,兩者的座標您希望裁剪到相對於固定的空間)。例如(從內存中寫的,未測試):

varying vec3 positionForClip; 
... 
void main(void) { 
    ... 
    vec4 worldPos = modelMatrix * vertexPosition; 
    positionForClip = worldPos.xyz/worldPos.w; // don't need homogeneous coordinates, so do the divide early 
    gl_Position = viewMatrix * worldPos; 
} 

而在你的片段着色器,你就可以放棄基於在任意平面,或任何其他類型的測試,你想:

varying vec3 positionForClip; 
uniform vec3 planeNormal; 
uniform float planeDistance; 
... 
void main(void) { 
    if (dot(positionForClip, planeNormal) > planeDistance) { 
     // or if (positionForClip.x > 10.0), or whatever 
     discard; 
    } 
    ... 
    gl_FragColor = ...; 
} 

注那麼使用discard可能會導致性能下降,因爲GPU無法在知道所有片段都將被寫入的情況下進行優化。

聲明:我自己沒有研究過這個,只是寫下了一個基於'明顯解決方案'的可能方法。可能有更好的方法,我沒有聽說過。


關於你提到的有關多個對象的問題:有很多不同的方式來處理這個問題 - 這是在結束時,所有的自定義代碼。但是當然,可以爲場景中的不同對象使用不同的着色器,只要它們位於不同的頂點數組中。

gl.useProgram(programWhichCuts); 
    gl.drawArrays(); 
    gl.useProgram(programWhichDoesNotCut); 
    gl.drawArrays(); 

如果你是第一次使用多個程序,它幾乎就像使用一個程序除非你做所有的設置(編譯,連接,鏈路)一次。要注意的主要是每個程序都有自己的制服,所以你必須分別爲每個程序初始化你的制服。

+0

性能下降是由丟棄還是由每個片段計算出來的dotProduct檢查引起的,儘管它們中的一部分是需要的?設置不透明度爲0是一種更有效的方式來實現這一點,或者它是相同的? (我對着色邏輯比較陌生) – 2014-03-03 23:54:47

+1

@konpsych任何包含'discard'語句的着色器[可能不適合某些優化](http://www.opengl.org/wiki/Early_Fragment_Test)。您不能在混合中使用透明度,而是在此「切割」中使用透明度,因爲透明區域仍會寫入深度緩衝區,可能會導致以後的幾何圖形不能被繪製。 – 2014-03-04 00:03:07

+0

通過查看[這個項目](http://open-3d-viewer.googlecode.com/svn/trunk/web/index.html)的透明度似乎工作得很好,我很確定它使用着色器,特別是第一個功能[這裏](https://code.google.com/p/open-3d-viewer/source/browse/trunk/web/scripts/shaders.txt) – 2014-03-05 20:06:28