背面剔除线条 [英] Back face culling for linestrips

查看:100
本文介绍了背面剔除线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在3D空间(图中红色)上有一个法线(白色)上的圆圈

I have circle in 3D space (red on image) with normals (white)

此圆圈被绘制为线条.

问题是:我只需要使用片段着色器代码中的丢弃来绘制法线指向相机的像素(法线与相机矢量之间的角度为<90).类似于背面剔除,但用于线条剔除.

Problem is: i need to draw only those pixels whose normals directed into camera (angle between normal and camera vector is < 90) using discard in fragment shader code. Like backface culling but for lines.

我需要绘制圆形的红色部分,而我需要在片段着色器中丢弃的黑色部分.

Red part of circle is what i need to draw and black is what i need to discard in fragment shader.

很好的例子是3DS Max旋转Gizmo,隐藏了行的背面:

Good example is 3DS Max rotation gizmo, back sides of lines are hidden:

所以,在片段着色器中,我有:

So, in fragment shader i have:

if(condition)
    discard;

帮我解决这个问题.同时考虑正交相机和透视相机.

Help me to come up with this condition. Considering both orthographic and perspective cameras would be good.

推荐答案

好,您已经描述了您的情况:

Well, you already described your condition:

(法线与相机矢量之间的夹角为< 90)

(angle between normal and camera vector is < 90)

您必须将法线转发到片段着色器(不要忘记在FS中对其进行规范化,插值会更改长度).并且您需要观看向量(与法线在同一空间中,因此您可能会将法线转换为眼睛空间,或者使用世界空间,甚至将视图方向/相机位置转换为对象空间).由于条件angle(N,V) >= 90 (degrees)cos(angle(N,V)) <= 0相同(假设归一化向量),因此您可以简单地使用点积:

You have to forward your normals to the fragment shader (don't forget to re-normalize it in the FS, the interpolation will change the length). And you need the viewing vector (in the same space than your normals, so you might transform normal to eye space, or use world space, or even transform the view direction/camera location into object space). Since the condition angle(N,V) >= 90 (degrees) is the same as cos(angle(N,V)) <= 0 (assuming normalized vectors), you can simply use the dot product:

if (dot(N,V) <= 0)
    discard;

更新:

正如您在评论中指出的那样,您拥有可用的经典" GL矩阵.因此,在眼部空间中进行此转换是有意义的.在顶点着色器中,您放置了

As you pointed out in the comments, you have the "classical" GL matrices available. So it makes sense to do this transformation in eye space. In the vertex shader, you put

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;
}

在片段着色器中,您可以轻松完成

and in the fragment shader, you can simply do

in vec3 normal_eyespace;
in vec3 vertex_eyespace;

void main()
{
    if (dot(normalize(normal_eyespace), normalize(-vertex_eyespace)) <= 0)
        discard;
    // ...
}

注意:该代码假定使用具有in/out而不是attribute/varying限定词的现代GLSL.我还假定没有内置属性.但是该代码应易于适应较旧的GL.

Note: this code assumes modern GLSL with in/out instead of attribute/varying qualifiers. I also assume no builtin attributes. But that code should be easily adaptable to older GL.

这篇关于背面剔除线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆