基于 "normals" 剔除线和点

Culling lines and points based on "normals"

我正在尝试在 WebGL 中模拟 glPolygonMode( GL_BACK, GL_LINE) 之类的东西。我可以使用模式 LINES 而不是 TRIANGLES 进行绘制,但我看不到 WebGL 如何自动确定特定段是否面向背面,因为段不会面向任何地方。

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

然而,这并不完全正确。我还需要投影矩阵的逆矩阵来考虑透视变形。

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

或者,是否有更好的方法来模拟 glPolygonMode( GL_BACK, GL_LINE)

求三角形的面积。如果是正数,就画出来,如果是负数,就剔除它。

如果可以选择使用 WebGl 扩展,您可能需要查看 OES_standard_derivatives. This extension was introduced for the specific purpose of solving your perspective correction issue. According to WebGL Stats 支持非常普遍。

在您的主代码库中,启用此扩展:

gl.getExtension("OES_standard_derivatives");

该扩展引入了 dFdx 和 dFdy 函数,允许您像这样进行 front/back 测试:

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

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

这是顶点着色器的关键部分。属性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; 

其中 front 是一个 bool 表示我是否要显示正面。