线条的背面剔除
Back face culling for linestrips
我有 3D 圆 space(图像上的红色)和法线(白色)
这个圆被绘制成线条。
问题是:我只需要在片段着色器代码中使用丢弃来绘制那些法线指向相机(法线和相机矢量之间的角度小于 90)的像素。类似于背面剔除,但用于线条。
圆圈的红色部分是我需要绘制的部分,黑色部分是我需要在片段着色器中丢弃的部分。
很好的例子 是 3DS Max 旋转 gizmo,线条的背面被隐藏:
所以, 在片段着色器中我有:
if(condition)
discard;
帮我想出这个条件。考虑到正交和透视相机会很好。
嗯,你已经描述了你的病情:
(angle between normal and camera vector is < 90)
你必须将你的法线转发给片段着色器(不要忘记在 FS 中重新规范化它,插值会改变长度)。并且您需要观察向量(与法线相同 space,因此您可以将法线转换为眼睛 space,或使用世界 space,甚至转换视图 direction/camera 定位到对象 space)。由于条件 angle(N,V) >= 90 (degrees)
与 cos(angle(N,V)) <= 0
相同(假设为归一化向量),您可以简单地使用点积:
if (dot(N,V) <= 0)
discard;
更新:
正如您在评论中指出的那样,您可以使用 "classical" GL 矩阵。所以在eye space中做这个变换是有意义的。在顶点着色器中,你把
in vec4 vertex; // object space position
in vec3 normal; // object space normal direction
out vec3 normal_eyespace;
out vec3 vertex_eyespace;
uniform mat3 normalMatrix;
uniform mat4 modelView;
uniform mat4 projection;
void main()
{
normal_eyespace = normalize(normalMatrix * normal);
vec4 v = modelViewMatrix * vertex;
vertex_eyespace = v.xyz;
gl_Position=projectionMatrix * v;
}
在片段着色器中,你可以简单地做
in vec3 normal_eyespace;
in vec3 vertex_eyespace;
void main()
{
if (dot(normalize(normal_eyespace), normalize(-vertex_eyespace)) <= 0)
discard;
// ...
}
注意:此代码假设现代 GLSL 具有 in
/out
而不是 attribute
/varying
限定符。我还假设没有内置属性。但是该代码应该很容易适应旧的 GL。
我有 3D 圆 space(图像上的红色)和法线(白色)
这个圆被绘制成线条。
问题是:我只需要在片段着色器代码中使用丢弃来绘制那些法线指向相机(法线和相机矢量之间的角度小于 90)的像素。类似于背面剔除,但用于线条。
圆圈的红色部分是我需要绘制的部分,黑色部分是我需要在片段着色器中丢弃的部分。
很好的例子 是 3DS Max 旋转 gizmo,线条的背面被隐藏:
所以, 在片段着色器中我有:
if(condition)
discard;
帮我想出这个条件。考虑到正交和透视相机会很好。
嗯,你已经描述了你的病情:
(angle between normal and camera vector is < 90)
你必须将你的法线转发给片段着色器(不要忘记在 FS 中重新规范化它,插值会改变长度)。并且您需要观察向量(与法线相同 space,因此您可以将法线转换为眼睛 space,或使用世界 space,甚至转换视图 direction/camera 定位到对象 space)。由于条件 angle(N,V) >= 90 (degrees)
与 cos(angle(N,V)) <= 0
相同(假设为归一化向量),您可以简单地使用点积:
if (dot(N,V) <= 0)
discard;
更新:
正如您在评论中指出的那样,您可以使用 "classical" GL 矩阵。所以在eye space中做这个变换是有意义的。在顶点着色器中,你把
in vec4 vertex; // object space position
in vec3 normal; // object space normal direction
out vec3 normal_eyespace;
out vec3 vertex_eyespace;
uniform mat3 normalMatrix;
uniform mat4 modelView;
uniform mat4 projection;
void main()
{
normal_eyespace = normalize(normalMatrix * normal);
vec4 v = modelViewMatrix * vertex;
vertex_eyespace = v.xyz;
gl_Position=projectionMatrix * v;
}
在片段着色器中,你可以简单地做
in vec3 normal_eyespace;
in vec3 vertex_eyespace;
void main()
{
if (dot(normalize(normal_eyespace), normalize(-vertex_eyespace)) <= 0)
discard;
// ...
}
注意:此代码假设现代 GLSL 具有 in
/out
而不是 attribute
/varying
限定符。我还假设没有内置属性。但是该代码应该很容易适应旧的 GL。