我想尝试一些有关现代渲染技术的新知识,并以此方式尝试实现自定义GI(在路径跟踪和即时光能传递之间的某个位置)。
我的场景和Tris小于1,000,000次需要多次将同一场景渲染为不同的微小纹理(我们称它们为“反弹”)。

我以一种幼稚的方式开始实现,所以我很快遇到了一些性能问题:
使用我的1TFlops笔记本电脑GPU,我可以渲染我的1M多边形场景,在降低30FPS波纹管之前可以有200次“反弹”。

我的“朴素”算法看起来像这样伪代码:

for (unsigned int i = 0; i < res ; ++i) {
  UpdateCameraUniform(i);
  glBindFramebuffer(GL_FRAMEBUFFER, BounceFbo[i]);
  glDrawBuffers(1, renderBuffer[i]);
  for (Mesh& m : Scene) {
    m.render();
  }
}




Mesh::render() {
UpdateTransformUniform();
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
}


完整代码在这里(该仓库真的很乱现在...)。

我需要找到一种渲染场景的新策略,所以我搜索了可以做什么。
我想我有2种策略:



尝试减少m的数量(或性能) y通话。似乎有一些魔术函数,例如glMultiDraw *(我在“ OpenGL超级”的文章中找到了它)。但是我真的不明白这是做什么的:


此渲染是否多次渲染相同的网格?
不同的网格但只有一个着色器?
不同的网格与


试图减少渲染时间,同时使用与之相同的技术在“ Bounces”中多次渲染相同的网格,但是我却完全不知道它是如何工作的,甚至可以应用于我...

显然我愿意接受任何其他建议。

编辑:我可以达到200次“反弹”,而不是35次

评论

@trichoplax是的,但是我的声誉不够高,无法放置2个以上的链接,因此我更改了它,然后忘了更改我的句子对不起= /我会解决的

我(终于)修复了

#1 楼

您应该始终进行剖析以确定减速发生的位置。从您的问题来看,目前尚不清楚您的工作是受CPU限制还是受GPU限制。


但是我真的不明白这是什么:这是否多次渲染同一网格?不同的网格,但只有一个着色器?不同的网格物体使用不同的着色器,但CPU开销较低?



glMultiDraw*绘制命令用于允许您在一个绘制调用中呈现多个对象。在OpenGL 3.0及更高版本中,这意味着您可以指定一个VBO来容纳一堆对象并使用glMultiDraw*渲染它们。您将使用同一着色器。如果要多次渲染同一对象,则使用实例化等方法将是一个很好的解决方案。

这一切都涉及绘制调用。如果只有少数几个网格具有一百万个三角形,则渲染将不会看到巨大的加速。您没有指定帧缓冲区的大小,但是如果帧缓冲区的大小足够小,则可能会导致许多小三角形的严重透支。如果图像真的那么小,也许您应该考虑添加LOD系统或使用较低的多边形网格和细分。


尝试减少渲染时间,同时渲染同一网格的多个时间在“弹跳”中使用与本技术相同的技术


立体声实例渲染是一种专门用于VR的技术。它基于这样的假设,即每只眼睛的场景几乎相同,因此它使用实例化一次渲染到屏幕的两侧。但是,如果弹跳渲染的几何形状相似,则只要弹跳是独立的,便可以将多个弹跳渲染到更大的帧缓冲区上。避免帧缓冲区切换(这是一个相当昂贵的过程)可能会提高速度。

在较新的OpenGL版本(4.0及更高版本)中,添加了对间接渲染的支持,该支持使您可以通过GPU计算来确定参数,但尚不清楚在这种情况下是否对您有帮助。

评论


$ \ begingroup $
当我达到20FPS时,我的CPU负载很少会超过30%,因此我受GPU约束。对于我现在的glMultiDraw *问题,我使用矩阵移动对象(UpdateTransformUniform()调用),是否可以将glMultiDrawElements链接到统一缓冲区或类似缓冲区?对于我的缓冲区,我的最终缓冲区是4 1920x1080(我正在使用延迟渲染),而跳动是4 64x64(很快将替换为1 64x64)。对于算法:我应该使用实例渲染在每个网格中循环弹跳,还是为每个反弹循环glMultiDraw我的网格。
$ \ endgroup $
–新闻
16-11-20在18:36

$ \ begingroup $
实际上,如果使用统一转换矩阵,则我想这就是您想要的:glDrawElementsInstancedBaseVertexBaseInstance(OpenGL 4.2)。这里是关于它的更多信息:gamedev.net/topic/…
$ \ endgroup $
–aces
16年11月21日在5:31

$ \ begingroup $
我问一个与您在这里问过类似的问题:computergraphics.stackexchange.com/questions/4241/…
$ \ endgroup $
–aces
16年11月21日在5:41

$ \ begingroup $
无论哪种方式,如果您的性能受到GPU的限制,都不会有太大的不同。对于64x64的网格,您将进行大量重绘,即使对于延迟的渲染器也是如此,因此您应该在此处进行优化。但是关于您的后续问题,我将浏览链接的幻灯片,看看是否可以帮助您解决这种情况(将其扩展到网格而不是两个屏幕)。
$ \ endgroup $
–aces
16年11月21日在5:42

$ \ begingroup $
好吧,我几乎是个好主意,最后一个问题:立体实例渲染似乎使用1个渲染目标,但分割成2个,但是我有多个FBO。我找不到跨多个FBO使用实例的方法,这是可能的吗?
$ \ endgroup $
–新闻
16-11-25在20:09

#2 楼

游戏中实时光能传递的一种常用方法是假定静态几何体,该几何体可用于预先计算空间中某个点(光探测器)的可见冲浪线(位置,反照率,法线)。这种方法避免了针对不同视点对几何图形进行运行时栅格化的需求。然后可以在运行时动态刷新这些surfel,并用于收集探测器的亮度,该亮度用于近似间接照明。