Получение позиций вершин в шейдере фрагментов
По определенной причине мне нужно получить положение всех вершин, которые образуют примитив (треугольник)в моем шейдере фрагментов.
Есть три способа сделать это: дополнительные атрибуты, униформа и геометрический шейдер.Атрибуты :
// vertex shader
in vec3 vPosition;
in vec3 vposA;
in vec3 vposB;
in vec3 vposC;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main() {
// ....
posA = vposA;
posB = vposB;
posC = vposC;
}
Проблема заключается в том, что мне нужно отправить дополнительные атрибуты, что означает дополнительную память, используемую в VBO.
Униформа :
// fragment shader
uniform vec3 posA;
uniform vec3 posB;
uniform vec3 posC;
void main() {
// ...
}
Главным недостатком, очевидно, является необходимость привязки униформ для каждого треугольника это рисуется, так что я могу нарисовать только один треугольник на каждый drawcall.
GS :
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main()
{
posA = gl_in[0].gl_Position.xyz;
posB = gl_in[1].gl_Position.xyz;
posC = gl_in[2].gl_Position.xyz;
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
С GS мне не нужно ничего хранить в памяти, я могу нарисовать столько треугольников, сколько захочу, но проблема в том, что используется весь новый этап шейдера.
Я также рассматривал возможность использования ключевого слова flat
, но здесь это не подходит.
Спасибо.
1 ответ:
Геометрические шейдеры являются наиболее практичным подходом, но это обычно исключает WebGL.
Вы можете рассмотреть возможность взять страницу из программируемого вытягивания вершин, где ваши фактические данные вершин хранятся в буферной текстуре, и вы используете индекс для поиска значений позиций. Я не могу комментировать производительность, но для этого потребуется значительно меньше памяти на вершину.
Вот модифицированная версия вашего исходного атрибута на основе попытка:
// vertex shader in int vIdxA; // Index of vtx 0 in current triangle in int vIdxB; // Index of vtx 1 in current triangle in int vIdxC; // Index of vtx 2 in current triangle out vec3 posA; out vec3 posB; out vec3 posC; uniform samplerBuffer vtx_buf; // Actual vertex position array, as a buffer texture void main() { int vtx = gl_VertexID % 3; // .... posA = texelFetch (vtx_buf, vIdxA); posB = texelFetch (vtx_buf, vIdxB); posC = texelFetch (vtx_buf, vIdxC); if (vtx == 0) gl_Position = posA; else if (vtx == 1) gl_Position = posB; else gl_Position = posC; }
Как реализовано, это также исключает WebGL, но должно быть проще адаптировать этот подход к OpenGL ES, чем что-то основанное на геометрическом шейдере.