GLSL Geometry shader для замены glLineWidth - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь написать геометрический шейдер, чтобы заменить 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();
}

Для полноты вот вершинный шейдер:

#version 330

in vec4 a_position;

void main() {
    gl_Position = a_position;
}

... и мой фрагментный шейдер:

#version 330

uniform vec4 u_color = vec4(1, 0, 1, 1);
out vec4 fragColor;

void main() {
    fragColor = u_color;
}

Я не могу заставить работать математикувсе ситуации.С ортогональной камерой все вышеперечисленное прекрасно работает:

Orthogonal camera, close by

Но с перспективной камерой проблема заключается в том, что линия не имеет фиксированный размер.Он становится все больше и меньше в зависимости от того, как далеко находится объект.

Perspective camera, close by

Perspective camera, far away

Я ожидал, что линия будет того же размера, используя перспективную камеру.Что я делаю неправильно?

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Мне удалось это исправить, учитывая размер области просмотра и масштабируя мой r, используя это.Я не знаю, является ли это наиболее эффективным способом решения этой проблемы (я ни в коем случае не математик), но он работает.

В приведенном ниже коде я сейчас делаю всю работу на экранепространство, а не пространство камеры / вида, и я использую u_viewportInvSize vec2 (который равен 1 / viewportSize), чтобы масштабировать желаемый радиус!

#version 330

layout (lines) in;                              // now we can access 2 vertices
layout (triangle_strip, max_vertices = 4) out;  // always (for now) producing 2 triangles (so 4 vertices)

uniform vec2    u_viewportInvSize;
uniform mat4    u_modelviewprojection_matrix;
uniform float   u_thickness = 4;

void main()
{
    float r = u_thickness;

    vec4 p1 = u_modelviewprojection_matrix * gl_in[0].gl_Position;
    vec4 p2 = u_modelviewprojection_matrix * 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 * u_viewportInvSize * (r * p1.w), 0, 0);
    offset2 = vec4(normal * u_viewportInvSize * (r * p1.w), 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) {
        gl_Position = coords[i];
        EmitVertex();
    }
    EndPrimitive();
}
0 голосов
/ 14 февраля 2019

Я не эксперт, но сделав это раньше, я предложу свое понимание.

Я предполагаю, что ваши gl_Position прямо от вершинного шейдера, который был рассчитан с помощью проекцииматрица.Это означает, что их 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;

Это должно дать вам нужный эффект.

...