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

Posted

技术标签:

【中文标题】在这种情况下我应该使用顶点着色器吗?【英文标题】:Should I use a vertex shader in this situation? 【发布时间】:2012-01-07 03:49:15 【问题描述】:

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

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

我最好的做法是什么?我正在选择:

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

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

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

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

在我看来,通过在 GPU 上执行顶点变换可能不会获得太多收益:我必须传入一个速度向量、一个角速度标量和一个质心向量作为顶点属性。这似乎是对带宽的极大浪费。但是,我可以将该数据用于可能大量的“样本”(子帧渲染)。

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

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

【问题讨论】:

【参考方案1】:

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

这当然是实现运动模糊的一种方法。但是现在运动模糊是通过片段着色器中的矢量模糊后处理过滤器实现的。请参阅http://www.blender.org/development/release-logs/blender-242/vector-blur/ 了解其工作原理。必须使用后处理着色器实时再现该过程。

【讨论】:

有趣的链接。谢谢。我正在渲染一个 2d 场景,而我正在尝试做的是利用快速的图形管道,通过多次渲染同一个对象而不是只渲染一次并处理它来产生更高保真度的结果。 @StevenLu:矢量模糊也适用于 2D。您所说的“快速图形管道”指的是什么? 我之前的 2d 运动模糊实现使用了带有片段着色器的方向模糊方法,问题是它也会模糊和混合移动对象附近的非移动对象,这是不可取的。否则看起来很棒。 我的意思是我可以发送大量的 2d 几何图形,而现代 3d 硬件可以像冠军一样处理它,因为它旨在处理大型 3d 网格。通过多次混合到同一个像素中,我可能会招致很多“过度绘制”,但没有一个是浪费的,因为它实际上正在做真正的长时间相机曝光所做的事情。 @StevenLu:但是这种运动模糊仍然只累积单个样本点。运气不好,你不会看到模糊,而是像“频闪仪”一样的图像。矢量模糊最酷的地方在于,它不容易出现这种伪影。此外,性能会更好,因为您只绘制了整个场景一次,然后 3 个全屏四边形在着色器中进行后期处理。不幸的是,我目前正在做其他事情,否则我会做一个示例实现。【参考方案2】:
    软件渲染子帧 - 将此视为“基线”情况。

    顶点着色器 - 你可以这样做,但不要尝试发送几何速度,只需发送顶点速度:

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

    然后,顶点着色器需要根据统一时间值应用偏移量。

    几何着色器 - 如果您使用它,您可以像 #2 一样实现它,除了“循环和变化”将在着色器中实现 - 有助于将更多工作卸载到 GPU。

你还提到:

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

【讨论】:

感谢您的分析。我对这个问题进行了更多思考,我意识到我想根据每个对象的移动速度来改变每个对象的样本数量。所以这就是我要做的:我在 cpu 上组装我的顶点缓冲区,其中包括所有的转换和使用 alpha 通道的适当混合值,我永远不需要编写顶点着色器。

以上是关于在这种情况下我应该使用顶点着色器吗?的主要内容,如果未能解决你的问题,请参考以下文章

在顶点着色器中定位顶点后如何更新法线?

顶点着色器 VAO 是不是需要 VBO?

从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”

使用顶点着色器确定线的方向

OpenGL - 动画是由着色器完成的吗?

✠OpenGL-13-几何着色器