我在3D空间中有圆圈(图像上的红色),带有法线(白色)
此圆圈被绘制为线条。
问题是:我需要使用片段着色器代码中的丢弃仅绘制其法线指向相机(法线和相机矢量之间的角度<90)的像素。像背面剔除但是线条。
圆圈的红色部分是我需要绘制的,黑色是我需要在片段着色器中丢弃的内容。
好例子是3DS Max旋转小发明,隐藏了线条的背面:
片段着色器中的
所以,我有:
if(condition)
discard;
帮我解决这个问题。考虑到正交和透视相机都会很好。
答案 0 :(得分:4)
嗯,你已经描述过你的病情了:
(法线和相机矢量之间的角度<90)
您必须将法线转发到片段着色器(不要忘记在FS中重新标准化,插值将改变长度)。并且您需要查看向量(与法线相同的空间,因此您可以将法线转换为眼睛空间,或使用世界空间,甚至将视图方向/相机位置转换为对象空间)。由于条件angle(N,V) >= 90 (degrees)
与cos(angle(N,V)) <= 0
相同(假设归一化向量),因此您只需使用点积:
if (dot(N,V) <= 0)
discard;
<强>更新强>
正如你在评论中指出的那样,你有&#34; classic&#34; GL矩阵可用。因此,在眼睛空间中进行此转换是有意义的。在顶点着色器中,放置
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。