Можно ли нарисовать шар с помощью нитей, используя уникальный геометрический шейдер?

Я хотел бы отобразить простую УФ-сферу (экспортированную из Blender) и генерировать линии с нормальными координатами, используя уникальный геометрический шейдер.

В первый раз я написал простой геометрический шейдер, который просто возвращает информацию о входных вершинах во фрагментный шейдер. Ради простоты (для примера) я стер расчеты яркости в фрагментном шейдере.

Вершинный шейдер:

#version 400

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

uniform mat4 MVP;

out vec3 VPosition;
out vec3 VNormal;

void main(void)
{
    VNormal = VertexNormal;
    gl_Position = vec4(VertexPosition, 1.0f);   
}

Геометрия шейдера:

#version 400

layout(points) in;
layout(line_strip, max_vertices = 2) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 2.5f;

    fcolor = vec3(0.0f, 0.0f, 1.0f);
    gl_Position = MVP * gl_in[0].gl_Position;
    EmitVertex();

    fcolor = vec3(1.0f, 1.0f, 0.0f);
    gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
    EmitVertex();

    EndPrimitive();
}

И фрагмент шейдера:

#version 400

in vec3 Position;
in vec3 Normal;
in vec2 TexCoords;

out vec4 FragColor;

in vec3 fcolor;

void main(void)
{
    FragColor = vec4(fcolor, 1.0f);
}

Теперь в коде C++ тип примитива для рисования (здесь треугольники):

glDrawArrays(GL_TRIANGLES, 0, meshList[idx]->getVertexBuffer()->getBufferSize());

И наконец вывод:

Пока здесь все в порядке. Теперь я хочу генерировать пряди на сфере как нормальные. Для выполнения этой работы я написал следующий геометрический шейдер (вершинный и фрагментный шейдеры одинаковы).

#version 400

layout(points) in;
layout(line_strip, max_vertices = 2) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 1.0f;

    fcolor = vec3(0.0f, 0.0f, 1.0f);
    gl_Position = MVP * gl_in[0].gl_Position;
    EmitVertex();

    fcolor = vec3(1.0f, 1.0f, 0.0f);
    gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
    EmitVertex();

    EndPrimitive();
}

Тип входного примитива - это точки. Я изменил код C++, чтобы нарисовать сцену:

glDrawArrays(GL_POINTS, 0, meshList[idx]->getVertexBuffer()->getBufferSize());

И вывод:

Наконец, если я хочу получить входной треугольник в качестве входного примитива и line_strip в качестве выходного примитива в геометрическом шейдере, у меня есть следующий шейдер:

#version 400

layout(triangles, invocations = 3) in;
layout(line_strip, max_vertices = 6) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 1.0f;

    for (int i = 0; i < 3; i++)
    {
        fcolor = vec3(0.0f, 0.0f, 1.0f);
        gl_Position = MVP * gl_in[i].gl_Position;
        EmitVertex();

        fcolor = vec3(1.0f, 1.0f, 0.0f);
        gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
        EmitVertex();

            EndPrimitive();
    }
}

И вывод следующий:

Но моя цель состоит в том, чтобы отобразить в одном выходе сцену (сфера + нити), используя один и тот же геометрический шейдер. Я хотел бы знать, возможно ли это сделать. Я так не думаю, потому что геометрический шейдер должен иметь только один тип входного примитива и другой тип на выходе, а не несколько типов. Я хочу быть уверен, возможно ли это или нет.

1 ответ

Решение

Кто знает, может быть, однажды будет расширение для испускания нескольких примитивных типов из геометрического шейдера, но, как вы говорите, в настоящее время это невозможно сделать.

Одна альтернатива может состоять в том, чтобы вместо этого нарисовать нормальные линии треугольниками.

Другим, но совершенно бесполезным в этом случае, может быть использование расширения обратной связи преобразования для сохранения результатов вершинного шейдера и повторного использования этих данных с двумя отдельными геометрическими шейдерами. Я упоминаю об этом только потому, что это самая близкая вещь, о которой я мог подумать - испускать несколько примитивных типов после стадии вершины.

РЕДАКТИРОВАТЬ
Два геометрических шейдера для рисования нормалей меня смущают. Во втором max_vertices = 3 , который должен быть 6 для 3 отдельных строк и EndPrimitive также должен быть внутри цикла for, чтобы 3 линии не были связаны. Но вы уже разобрались с этим, нарисовав GL_POINTS в предыдущем. Предполагается ли это структурировать для нескольких примитивных выходных данных, если они поддерживаются? (фиксированный)

Учитывая, что ваша геометрия использует много вершин, индексы с glDrawElements будет более эффективным. Хотя вы все еще хотите использовать glDrawArrays для рисования нормальных линий, чтобы избежать рисования дубликатов вершин, на которые ссылается индексный массив.

Другие вопросы по тегам