遮挡查询和实例渲染

时间:2016-01-11 17:29:07

标签: opengl

我遇到了一个问题,那就是需要使用遮挡查询和实例化渲染。

据我所知,有点像

glBeginQuery(GL_ANY_SAMPLES_PASSED, occlusionQuery);
glDrawArraysInstanced(mode, i, j, countInstances);
glEndQuery(GL_ANY_SAMPLES_PASSED);

只会告诉我,是否有任何实例。 我需要知道的是,绘制了哪些实例(给我所有可见实例的ID)。在我自己的电话中绘制每个实例对我来说都是不可取的。

另一种方法是对实例进行颜色编码并手动检测可见实例。 但是真的没有办法用查询命令解决这个问题,为什么不可能呢?

1 个答案:

答案 0 :(得分:3)

由于多种原因,这是不可能的。

  1. Query objects只包含一个计数器值。您想要的是每个实例需要单独的样本传递计数。

  2. 即使查询对象存储了样本计数数组,您也可以在begin/end scope of a query中发出多个绘图调用。那么OpenGL如何知道哪个绘制调用部分属于数组中的哪个查询值?您甚至可以在查询范围内更改其他状态;统一绑定,程序,几乎任何东西。

  3. 样本传递计数完全由GPU上的光栅化器硬件决定。并且光栅化器既不知道也不关心哪个实例生成了三角形。

    实例化是vertex processing和/或vertex specification阶段的函数;当光栅化器看到它时,该信息就消失了。请注意片段着色器don't even get an instance ID as input,除非您通过从顶点处理阶段传递它来明确创建它。

  4. 但是,如果您真的想要这样做,可以使用image load/store及其原子操作。也就是说,将片段着色器传递给相关实例(作为int数据类型,并使用flat插值)。此FS还使用uimageBuffer缓冲区纹理,该纹理使用GL_R32UI格式(或者您可以使用SSBO无界数组)。然后使用传入的实例值作为缓冲区的索引,执行imageAtomicAdd。哦,你需要拥有FS explicitly require early tests,这样不能执行片段测试失败的样本。

    然后使用compute shader为数组中具有非零值的实例构建渲染命令列表。然后使用indirect rendering调用来绘制此计算的结果。显然,您需要在这些不同的操作之间正确同步访问。因此,您需要在每个调用之间使用适当的glMemoryBarrier调用。

    即使查询按照您希望的方式工作,这总体上比使用查询对象更可取。除非您reading a query into a buffer object,否则读取查询对象需要某种形式的GPU / CPU同步。虽然上述需要一些同步和屏障操作,但它们都是GPU上的操作,而不是与CPU同步。