fod*_*dex 6 opengl glsl line geometry-shader
我正在尝试编写一个几何着色器来替换glLineWidth行为。我想绘制具有可自定义宽度的线条(现在使用统一的线条就足够了)。无论相机投影或与线条所在位置的距离如何,线条应始终具有相同的粗细。
基于大量的谷歌搜索,我想出了以下几何着色器:
#version 330
layout (lines) in;
layout (triangle_strip, max_vertices = 4) out;
uniform mat4 u_model_matrix;
uniform mat4 u_view_matrix;
uniform mat4 u_projection_matrix;
uniform float u_thickness = 4; // just a test default
void main()
{
float r = u_thickness / 2;
mat4 mv = u_view_matrix * u_model_matrix;
vec4 p1 = mv * gl_in[0].gl_Position;
vec4 p2 = mv * gl_in[1].gl_Position;
vec2 dir = normalize(p2.xy - p1.xy);
vec2 normal = vec2(dir.y, -dir.x);
vec4 offset1, offset2;
offset1 = vec4(normal * r, 0, 0);
offset2 = vec4(normal * r, 0, 0);
vec4 coords[4];
coords[0] = p1 + offset1;
coords[1] = p1 - offset1;
coords[2] = p2 + offset2;
coords[3] = p2 - offset2;
for (int i = 0; i < 4; ++i) {
coords[i] = u_projection_matrix * coords[i];
gl_Position = coords[i];
EmitVertex();
}
EndPrimitive();
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,这里是顶点着色器:
#version 330
in vec4 a_position;
void main() {
gl_Position = a_position;
}
Run Code Online (Sandbox Code Playgroud)
...和我的片段着色器:
#version 330
uniform vec4 u_color = vec4(1, 0, 1, 1);
out vec4 fragColor;
void main() {
fragColor = u_color;
}
Run Code Online (Sandbox Code Playgroud)
我无法让数学在所有情况下都发挥作用。使用正交相机,上述效果很好:
但对于透视相机来说,问题在于线条不是固定大小的。相对于物体距离的远近,它会变得更大或更小。
我预计使用透视相机时该线的尺寸也相同。我究竟做错了什么?
我不是专家,但我以前做过这件事,所以我会提供我的见解。
我假设你的gl_Positions 直接来自使用投影矩阵计算的顶点着色器。这意味着它们的w分量是点的“剪辑空间位置”;这就是管道用来赋予投影效果的东西(越远的东西越小)。所以需要考虑到这一点。
幸运的是,您唯一需要做的就是将偏移量乘以它。
coords[0] = p1 + offset1 * p1.w;
coords[1] = p1 - offset1 * p1.w;
coords[2] = p2 + offset2 * p2.w;
coords[3] = p2 - offset2 * p2.w;
Run Code Online (Sandbox Code Playgroud)
这应该会给你你想要的效果。