Если я настраиваю пользовательский восходящий целочисленный поток буфера вершин drawID для данных каждого экземпляра с помощью:
glVertexAttribDivisor(drawIDVertexStreamIdx, 1)
Используя заданную glMultiDrawElementsIndirect ():
struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};
При установке instanceCount на большечем один, я смущен, глядя на старые заметки и онлайн о том, что именно происходит с drawID, переданным шейдеру?
Если, скажем, есть две записи DrawElementsIndirectCommand, вызванные из одной glMultiDrawElementsIndirect (), причем первая запись имеетinstanceCount, равный 3, а второй instanceCount, скажем, 1, что в действительности видят экземпляры в шейдере?(Предполагая, что поток вершин drawID содержит 0,1,2,3 и т. Д.)
Должны ли они видеть 0,1,2 для первых экземпляров записи DrawElementsIndirectCommand и 3 для второго экземпляра записи DrawElementsIndirectCommand?
Все примеры, которые я могу найти в Интернете, по-видимому, специально устанавливают instanceCount равным единице и полагаются на несколько записей DrawElementsIndirectCommand, что заставляет меня теперь сомневаться в правильности этого понимания?
const int CustomDrawIDIdx = 1;
const int VertexCount = 4;
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 0 },
};
...
// Attempt to set up custom drawID from a vertex attribute, where the vertex stream for it is a sequence of integers 0, 1, 2 etc
glVertexAttribIPointer(CustomDrawIDIdx, 1, GL_UNSIGNED_INT, 0, NULL);
glVertexAttribDivisor(CustomDrawIDIdx, 1);
...
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, &drawCallRecords, 2, 0);
В вершинном шейдере:
layout (location = 1) in uint customDrawID;
void main()
{
bool match = (customDrawID== gl_InstanceID);
...
}
Таким образом, это должно вызвать 4 фактических вызова отрисовки, поскольку фактические вызовы отрисовки, вызванные glMultiDrawElementsIndirect (), определяются числом записей DrawElementsIndirectCommand и их количеством содержащихся экземпляров.
Для каждого вызова отрисовки gl_InstanceID долженначинать с нуля и считать для каждого экземпляра, но возвращаться к нулю после обработки каждой записи DrawElementsIndirectCommand?
Таким образом, gl_InstanceID должен делать (0, 1, 2) для drawCallRecords [0], а затем (0)для drawCallRecords [1]?Что делает customDrawID?
Мне также любопытно, если ARB_shader_draw_parameters на nVidia (GTX1070 +) все еще не рекомендуется по сравнению с использованием настраиваемого drawID из потока вершин?
*** UPDATE для отраженияОтвет очень терпеливого и полезного Никола Боласа:
Итак, учитывая:
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};
Затем customDrawID будет выполнять (0, 1, 2) и (3) во всех случаях вmultidrawindirect.
Это означает, что каждый отрисованный экземпляр через два вызова отрисовки и 3 + 1 отрисованных экземпляров (3 экземпляра одного «объекта», 1 экземпляр другого «объекта») в одном вызове multidrawindirectможет ссылаться на совершенно уникальные матрицы преобразования, например.И, по сути, это эмулирует функциональность gl_DrawID, пока вы продолжаете увеличивать baseInstance как этот (исключительный стиль суммы) для каждой записи DrawElementsIndirectCommand.
BaseInstance в каждой записи DrawElementsIndirectCommand будет сдвигать смещение в поток вершин customDrawID, давая customDrawID, который уникален для каждого экземпляра среди всех нарисованных объектов.