Можно ли нарисовать шар с помощью нитей, используя уникальный геометрический шейдер?
Я хотел бы отобразить простую УФ-сферу (экспортированную из 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
для рисования нормальных линий, чтобы избежать рисования дубликатов вершин, на которые ссылается индексный массив.