我目前正在实现Oikonomidis等人,2011年提出的姿势估计算法,该算法涉及在N
不同的假设姿势中渲染网格(N
可能约为64)。第 2.5 节建议通过使用实例化同时生成多个渲染来加快计算速度(之后他们将每个渲染减少到 GPU 上的单个数字),从他们的描述来看,听起来他们找到了一种同时生成N
渲染的方法。
在实现的设置阶段,我使用 OpenGL 视口数组来定义GL_MAX_VIEWPORTS
视口。然后在渲染阶段,我将GL_MAX_VIEWPORTS
模型姿势矩阵的数组传输到 GPU 内存中的mat4
uniform
数组(我只对估计位置和方向感兴趣),并在几何着色器中使用gl_InvocationID
为网格的每个多边形选择适当的姿势矩阵和视口。
GL_MAX_VIEWPORTS
在我的机器上是 16(我有一个 GeForce GTX Titan),所以这种方法将允许我在 GPU 上一次呈现多达 16 个假设。这可能足够快,但我仍然对以下内容感到好奇:
对于GL_MAX_VIEWPORTS
限制,是否有一种解决方法可能比调用我的渲染函数ceil(double(N)/GL_MX_VIEWPORTS)
次更快?
几周前我才开始学习基于着色器的OpenGL方法,所以我还不知道所有的技巧。我最初考虑将内置视口支持替换为以下组合:
- 一个几何着色器,用于在透视投影后向顶点的
y
坐标添加h*gl_InvocationID
(其中h
是所需的视口高度),并将gl_InvocationID
传递到片段着色器上;以及 - 一个片段着色器,
discard
具有满足y<gl_InvocationID*h || y>=(gl_InvocationID+1)*h
y
坐标的片段。
但是我推迟了对这个想法的进一步调查,因为担心分支和discard
会对性能非常有害。
上面论文的作者发布了一份技术报告,描述了他们的一些GPU加速方法,但它不够详细,无法回答我的问题。第 3.2.3 节说"在几何实例化期间,视口信息附加到每个顶点......自定义像素着色器可剪辑其预定义视口之外的像素"。这听起来类似于我上面描述的解决方法,但他们使用的是 Direct3D,因此将他们在 2011 年能够实现的目标与我今天在 OpenGL 中实现的目标进行比较并不容易。
我意识到我的问题的唯一明确答案是实施解决方法并衡量其性能,但它目前是一个低优先级的好奇心,我还没有在其他任何地方找到答案,所以我希望更有经验的 GLSL 用户能够提供他们节省时间的智慧。
粗略地看了一眼论文,在我看来,实际的视口并没有改变。也就是说,您仍然渲染到具有相同深度范围的相同宽度/高度和 X/Y 位置。
您想要的是更改要渲染到的图像。这就是gl_Layer
的目的;以更改附加到帧缓冲区的图像分层数组中的哪个层。
因此,只需将所有顶点的gl_ViewportIndex
设置为 0。或者更具体地说,根本不设置它。
GS 实例化调用的数量不必是限制;这是您的选择。GS 调用可以将多个基元写入多个基元,每个基元写入不同的层。因此,您可以让每个实例写入 4 个基元,每个基元写入 4 个单独的层。
您唯一的限制应该是您可以使用的层数(由GL_MAX_ARRAY_TEXTURE_LAYERS
和GL_MAX_FRAMEBUFFER_LAYERS
控制,两者都必须至少为 2048),以及单个 GS 调用可以发出的基元和顶点数据的数量(这有点复杂)。