基于“法线”剔除线条和点

时间:2016-12-27 12:31:05

标签: webgl

我正在尝试在WebGL中模拟glPolygonMode( GL_BACK, GL_LINE)之类的内容。我可以使用模式LINES而不是TRIANGLES进行绘制,但我无法看到WebGL如何自动确定特定细分是否面向背面,因为细分不会面向任何位置。

为了解决这个问题,我将原始三角形的法线传递给着色器。在通常的模型视图转换(旋转,缩放,平移)下计算变换很容易;那么我只需将法线乘以逆的转置。根据是否正常指向屏幕还是我可以决定是否剔除一个线段。

但是,这不太对。我还需要投影矩阵的逆矩阵来考虑透视失真。

我正在使用CanvasMatrix4.frustum()CanvasMatrix4.ortho()函数来获取投影矩阵。是否有可用于反转的公式或函数?

或者,有没有更好的方法来模拟像glPolygonMode( GL_BACK, GL_LINE)这样的东西?

3 个答案:

答案 0 :(得分:1)

将三角形的其他顶点作为额外属性发送的想法似乎有效。

这是顶点着色器的关键部分。属性aPos是在线段中使用的顶点的位置; v1是围绕三角形的下一个顶点,v2是之后的那个顶点。

我编辑了代码以省略与照明相关的内容。这可能不是最有效的实现,但它似乎确实有效。

attribute vec3 aPos;
uniform mat4 mvMatrix;
uniform mat4 prMatrix;
attribute vec3 v1;
attribute vec3 v2;
varying float normz;

void main(void) {
    gl_Position = prMatrix * (mvMatrix * vec4(aPos, 1.));
    vec4 v1p = (prMatrix*(mvMatrix*vec4(v1, 1.)));
    v1p = v1p/v1p.w - gl_Position/gl_Position.w;
    vec4 v2p = (prMatrix*(mvMatrix*vec4(v2, 1.)));
    v2p = v2p/v2p.w - gl_Position/gl_Position.w;
    normz = v1p.x*v2p.y - v1p.y*v2p.x; // z component of cross product
}

在片段着色器中,根据normz的符号丢弃片段。我用

if ((normz <= 0.) != front) discard; 

其中frontbool,表示我是否要显示正面。

答案 1 :(得分:0)

如果使用WebGl扩展是一个选项,您可能需要查看OES_standard_derivatives。此扩展是为了解决您的透视校正问题的特定目的而引入的。根据{{​​3}}支持是非常普遍的。

在主代码库中,启用此扩展程序:

gl.getExtension("OES_standard_derivatives");

该扩展程序引入了dFdx和dFdy函数,允许您进行这样的前/后测试:

vec3 dx = dFdx(position);
vec3 dy = dFdy(position);
vec3 faceNormal = normalize(cross(dx, dy));
if (dot(normal, faceNormal) > 0.0) {
    // Front facing
}

答案 2 :(得分:-1)

取三角区域。如果它是正数,如果它是负数则绘制它,剔除它。