Luc*_*uca 5 opengl glsl geometry-shader
我正在尝试使用几何着色器渲染任意宽线(在屏幕空间中)。乍一看似乎一切都很好,但是在某些视图位置上,线条显示不正确:
左侧的图像呈现正确的渲染效果(正X,Y和Z轴上的三条线,宽度为2像素)。
当摄像机移动到原点附近(实际上是在线条附近)时,线条就像正确的图像一样呈现。着色器似乎很简单,我不了解我的GPU上发生了什么:
--- Vertex Shader
#version 410 core
// Modelview-projection matrix
uniform mat4 ds_ModelViewProjection;
// Vertex position
in vec4 ds_Position;
// Vertex color
in vec4 ds_Color;
// Processed vertex color
out vec4 ds_VertexColor;
void main()
{
gl_Position = ds_ModelViewProjection * ds_Position;
ds_VertexColor = ds_Color;
}
--- Geometry Shader
#version 410 core
// Viewport size, in pixels
uniform vec2 ds_Viewport;
// Line width, in pixels
uniform float ds_LineWidth = 2.0;
// Processed vertex color (from VS, in clip space)
in vec4 ds_VertexColor[2];
// Processed primitive vertex color
out vec4 ds_GeoColor;
layout (lines) in;
layout (triangle_strip, max_vertices = 4) out;
void main()
{
vec3 ndc0 = gl_in[0].gl_Position.xyz / gl_in[0].gl_Position.w;
vec3 ndc1 = gl_in[1].gl_Position.xyz / gl_in[1].gl_Position.w;
vec2 lineScreenForward = normalize(ndc1.xy - ndc0.xy);
vec2 lineScreenRight = vec2(-lineScreenForward.y, lineScreenForward.x);
vec2 lineScreenOffset = (vec2(ds_LineWidth) / ds_ViewportSize) * lineScreenRight;
gl_Position = vec4(ndc0.xy + lineScreenOffset, ndc0.z, 1.0);
ds_GeoColor = ds_VertexColor[0];
EmitVertex();
gl_Position = vec4(ndc0.xy - lineScreenOffset, ndc0.z, 1.0);
ds_GeoColor = ds_VertexColor[0];
EmitVertex();
gl_Position = vec4(ndc1.xy + lineScreenOffset, ndc1.z, 1.0);
ds_GeoColor = ds_VertexColor[1];
EmitVertex();
gl_Position = vec4(ndc1.xy - lineScreenOffset, ndc1.z, 1.0);
ds_GeoColor = ds_VertexColor[1];
EmitVertex();
EndPrimitive();
}
--- Fragment Shader
// Processed primitive vertex color
in vec4 ds_GeoColor;
// The fragment color.
out vec4 ds_FragColor;
void main()
{
ds_FragColor = ds_GeoColor;
}
Run Code Online (Sandbox Code Playgroud)
小智 6
您的错误在于:
gl_Position = vec4(ndc0.xy + lineScreenOffset, ndc0.z, 1.0 /* WRONG */);
Run Code Online (Sandbox Code Playgroud)
要解决这个问题:
vec4 cpos = gl_in[0].gl_Position;
gl_Position = vec4(cpos.xy + lineScreenOffset*cpos.w, cpos.z, cpos.w);
Run Code Online (Sandbox Code Playgroud)
您要做的是:丢失有关W的信息,从而使HW裁剪器失谐,将其从3D裁剪器降级为2D裁剪器。
今天我自己找到了答案。我不完全理解,但这解决了问题。
当线顶点超出为场景定义的投影矩阵的近平面时(在我的例子中,是三条线的所有结束顶点),就会出现问题。解决方案是手动裁剪视锥体内的线顶点(这样顶点就不能超出近平面!)。
当它们离开视锥体时会ndc0
发生什么?ndc1
查看图像,似乎 XY 分量的符号发生了变化(在剪辑空间中进行变换后!):这意味着 W 坐标与正常坐标相反,不是吗?
如果没有几何着色器,光栅化器将负责将这些图元裁剪到视锥体外,但由于我引入了几何着色器,我需要自己计算这些结果。有人可以建议我一些关于此事的链接吗?
归档时间: |
|
查看次数: |
2578 次 |
最近记录: |