线条的背面剔除

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。