如果我使用以下方法为每个实例数据设置了一个定制的递增整数drawID顶点缓冲流:
glVertexAttribDivisor(drawIDVertexStreamIdx, 1)
使用给定的glMultiDrawElementsIndirect():
struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};
当将instanceCount设置为一个以上时,我困惑地看着旧笔记和网上关于将drawID传递给着色器的确切情况?
如果说有两个从一个glMultiDrawElementsIndirect()调用的DrawElementsIndirectCommand记录,第一个记录的instanceCount为3,第二个记录的instanceCount为1,则实例在着色器中实际看到了什么? (假设drawID顶点流包含0、1、2、3等)
他们是否应该为第一个DrawElementsIndirectCommand记录实例看到0,1,2,并为第二个DrawElementsIndirectCommand记录实例看到3,
我在网上可以找到的所有示例似乎都将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应该对drawCallRecords [0]做(0,1,2),然后对drawCallRecords [1]做(0)? customDrawID有什么作用?
我还是很好奇,还是不建议与使用来自顶点流的自定义drawID相比,在nVidia(GTX1070 +)上使用ARB_shader_draw_parameters?
***更新以反映非常耐心和乐于助人的Nicol Bolas的答案:
所以给定了:
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};
然后,customDrawID将对multidrawindirect中的所有实例进行(0,1,2)和(3)。
这意味着在两次multidrawindirect调用中,两次绘制调用中的每个绘制实例以及绘制的3 + 1总实例(一个“对象”的3个实例,另一个“对象”的1个实例)可以引用完全唯一的变换例如矩阵。实质上,只要您为每个DrawElementsIndirectCommand记录不断增加baseInstance这样的值(独占和样式),就可以模拟gl_DrawID的功能。
每个DrawElementsIndirectCommand记录中的baseInstance会将偏移量推送到customDrawID顶点流中,从而提供一个customDrawID,该ID对于所有绘制的对象中的每个实例都是唯一的。
答案 0 :(得分:3)
因此,这应该引起4次实际的绘图调用,因为由glMultiDrawElementsIndirect()引起的实际绘图调用由DrawElementsIndirectCommand记录的数量及其包含的实例数确定。
不。实例和“绘图调用”不是一回事。
定义一次绘图调用,就像通过调用glDraw*InstancedBaseVertexBaseInstance
来定义;当系统从绘制数据数组中读取单个条目时,就会发生这种情况。单个绘图调用包括所有实例。实例化是在抽奖中发生的事情。
这也是为什么每个实例的值不能保证为dynamically uniform expressions的原因。
多绘制命令中的单独绘制gl_DrawID
放在一边,彼此完全分开。他们不互动。着色器为实例数组或gl_InstanceID
获取的值与分别发出每个绘图调用没有什么不同。
您的“自定义drawID”根本不是绘图ID;它是一个实例数组值。因此,它遵循实例化规则,并且不关心什么所在的绘制调用。
bool match = (customDrawID== gl_InstanceID);
否。
即使您用于馈送customDrawID
的实际数组只是从零开始的整数索引,实例数组和gl_InstanceID
的工作方式也不相同。
gl_InstanceID
忽略基本实例。实例数组不。这样,从任何实例数组中获取的实例值将始终始终先由基本实例偏移。
因此,如果您希望特定绘图调用的customDrawID
从特定值开始,则可以将baseInstance
设置为该特定值的实例索引。因此,给定一个从零开始的整数索引数组,如果希望特定的绘制调用使其第一个实例接收customDrawID
的值“ 3”,则可以将baseInstance
设置为3。