在这种情况下,我应该使用顶点着色器吗

Should I use a vertex shader in this situation?

本文关键字:顶点 这种情况下 我应该      更新时间:2023-10-16

我想通过在一帧的过程中渲染和添加混合运动对象轨迹中的多个点来创建运动模糊效果。

我认为可以在顶点着色器中执行用于确定绘制位置的计算。不过,在我看来,如果我想避免为每个渲染传递几何体,我可能需要使用几何体着色器。

我的最佳行动方案是什么?我在以下两者之间做出决定:

  1. 手动组装每个子帧的顶点数据,并每次将其传递给GPU(如果我这样做,我就不需要顶点程序)
  2. 将几何体与速度值一起发送。我可以计算顶点着色器中的中间位置,但我不确定如何指定将某个速度值指定给某些基元组。我需要为每个子帧渲染发送一次相同的顶点,因为顶点着色器无法创建新的顶点
  3. 使用几何体着色器为所有子帧生成所有几何体。在整个渲染过程中,我应该能够获得所有的子帧,而无需来回传递任何数据

我想在这里取得的平衡是,我希望在支持尽可能多的硬件的同时,将冗余数据传递降至最低。似乎我应该能够使用"顶点缓冲区对象"来存储几何体数据,并且只需传递一些统一即可在每次渲染时将速度数据发送到顶点着色器。这样行吗?VBO缓冲区也是持久的,所以为了获得最佳性能,我应该根据需要介入并修改几何数据,对吗?

另一个我不知道如何处理的潜在问题是,我想通过插值刚性对象在帧上经过的平移和旋转来准确地绘制中间位置,而不仅仅是插值得到的顶点位置。这里的区别在于旋转的物体会留下弯曲的条纹。

有没有什么方法可以防止为每个单独的动态刚性对象发出调用?也许我可以使用一个通用的顶点属性来发送我的速度?这会有点多余,因为我可以有一个有100个顶点的对象,具有相同的速度数据,但至少我的着色器可以通过这种方式获得这些数据流。

在我看来,在GPU上执行顶点变换可能不会有太多好处:我必须输入速度向量、角速度标量和质心向量作为顶点属性。这似乎是对带宽的巨大浪费。然而,我可以将该数据用于潜在的大量"采样"(子帧渲染)。

我已经使用OpenGL即时模式度过了很长一段时间,但这次我想做正确的事情。

更新:请参阅扩展评论讨论,了解它的发展方向。我现在相当确定,由于"闪光灯效应",多个样本不会产生好的结果:在某些速度下,出于性能原因,我需要使用模糊。在这种情况下,我需要积累模糊的子帧;渲染子帧然后模糊它仍然会留下伪影。

我想通过在一帧的过程中渲染和添加混合运动对象轨迹中的多个点来创建运动模糊效果。

这当然是实现运动模糊的一种方法。但如今,运动模糊是通过片段着色器中的向量模糊后处理过滤器实现的。看见http://www.blender.org/development/release-logs/blender-242/vector-blur/以了解其工作原理。为了实时,必须使用后期处理着色器来再现该过程。

  1. 软件渲染子帧-将此视为"基线"情况
  2. 顶点着色器-你可以这样做,但不要试图发送几何体速度,只发送顶点速度:

    将帧渲染到VBO,调用glVertexAttrib以包括每个顶点的当前速度和加速度。重复渲染VBO,使用统一值指定每个子帧的时间偏移。

    然后顶点着色器将需要基于统一时间值应用偏移。

  3. 几何着色器-如果你这样做,你可以像#2一样实现它,只是"循环和变化"将在着色器中实现-有助于将更多的工作转移到GPU。

您还提到:

  • 用VBO渲染所有内容-如果你像这样使用VBO/显示列表,你基本上会用更多的硬件加速来做选项#1
  • 插值问题-这可能不值得你努力得到一个精确的插值。除非对象移动非常快弯曲,否则速度的线性插值(一阶)可能很好。你可以通过包括加速度(二阶)来改进它,但额外的阶数或更准确的物理模型可能值得付出努力或成本
  • 也许不值得——这才是真正的问题所在。根据您的应用程序、硬件和其他细节,这些可能的解决方案中的任何一个都可能优于另一个。如果性能很重要,您可能应该尝试每个的原型实现,并在目标设备上运行基准测试,看看什么最适合。(可悲的现实是,在完成所有工作之前,你无法轻松执行基准测试。)