如何使用WebGL着色器剪切对象?

时间:2013-05-13 13:10:12

标签: javascript 3d webgl shader

我想在WebGLfragment shaders / vertex shaders)中剪切一个对象(一个框)而不使用布尔运算(并集,差异等等)。

我想使用着色器来隐藏对象的某些部分(因此它实际上不是“真正的剪切”,因为它只是隐藏了对象)。

修改

1 个答案:

答案 0 :(得分: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();

如果您不习惯使用多个程序,那么除了您完成所有设置(编译,附加,链接)之外,它几乎就像使用一个程序一样。需要注意的是每个程序都有自己的制服,所以你必须分别为每个程序初始化你的制服。