我正在尝试在WebGL中模拟glPolygonMode( GL_BACK, GL_LINE)
之类的内容。我可以使用模式LINES
而不是TRIANGLES
进行绘制,但我无法看到WebGL如何自动确定特定细分是否面向背面,因为细分不会面向任何位置。
为了解决这个问题,我将原始三角形的法线传递给着色器。在通常的模型视图转换(旋转,缩放,平移)下计算变换很容易;那么我只需将法线乘以逆的转置。根据是否正常指向屏幕还是我可以决定是否剔除一个线段。
但是,这不太对。我还需要投影矩阵的逆矩阵来考虑透视失真。
我正在使用CanvasMatrix4.frustum()
或CanvasMatrix4.ortho()
函数来获取投影矩阵。是否有可用于反转的公式或函数?
或者,有没有更好的方法来模拟像glPolygonMode( GL_BACK, GL_LINE)
这样的东西?
答案 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;
其中front
是bool
,表示我是否要显示正面。
答案 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)
取三角区域。如果它是正数,如果它是负数则绘制它,剔除它。