2013-05-13 39 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