65.9K
CodeProject 正在变化。 阅读更多。
Home

全场景运动模糊

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (26投票s)

2005年3月28日

CPOL

4分钟阅读

viewsIcon

135336

downloadIcon

3582

如何获得运动模糊效果。

Sample Image - Motion Blur Effect.jpg

引言

运动模糊是一个非常出色的效果,但制作起来却很困难。为了获得这种效果,OpenGL 开发者推荐使用累积缓冲区。基本上,累积缓冲区通过使用不同的 alpha 值重绘对象 n 次。我并不反对这种方法,但是当场景中充满了“难以渲染”的对象时,它会导致低 FPS。在全场景运动模糊中,为了获得效果,场景必须被绘制更多次。最大的问题来自于累积缓冲区,它并非在所有图形卡上都得到支持。那么如何解决这个问题呢?

背景

我将在下面解释的一种非常好的方法是将我们的场景渲染到纹理中。这有什么用?很简单,通过将对象渲染到纹理中,我们可以轻松访问上一帧,通过访问它,我们可以以较低的 alpha 值渲染它。以递归的方式进行,我们可以获得期望的效果。

唯一需要的是一个用于存储上一帧场景的纹理。算法现在很简单:

  1. 绘制旧场景(存储在纹理中,这是一个简单的纹理多边形), alpha 值较低(<1)。
  2. 绘制当前场景。
  3. 将整个屏幕读取到纹理中。

使用此实现,该效果仅在对象外部可见,对象在其余部分看起来相同。但我们都知道,运动模糊的效果是对象本身模糊,而不仅仅是围绕对象的简单轨迹。那么我们该如何实现呢?很简单:先绘制场景,然后渲染旧场景。这样做,对象就会显得模糊。

这种方法不是最好也不是最差,它只是一种方法,我希望它能帮助许多其他人,因为它帮助了我。

使用代码

小型演示展示了该效果如何在单个对象和整个场景上工作。单个对象是一个纹理立方体,整个场景是一个漩涡效果。

对于每个基本实用程序,都存在一个不同的模块。核心(主)模块包含所有可能在其他模块中需要的定义。下一级别有三个模块:glBasic(处理初始化和其他 GL 相关事宜),glDraw(处理所有 GL 绘图)和 keyboard(处理键盘管理例程)。glDrawmotionblur(存储渲染运动模糊所需的程序 - 这就是为什么整个应用程序都围绕它构建)和 tunnel(保存顶点创建和处理)有关。glBasic 调用纹理模块(纹理处理)。(注意 - 模块在物理上由 C 文件表示,代码不使用 OOP。)

用于运动模糊的纹理在核心(主)模块中定义,并导出到所有其他模块。但是处理是在 motionblur 模块中进行的。有三个过程:

  1. int CreateMotionBlurTexture(int quality, int interpolation); - 创建运动模糊纹理,建议在 init 过程中调用。
  2. void RenderToMotionBlurTexture(bool FirstRenderTexture, int SceneFunc()); - 将 SceneFunc() 与上一帧一起“渲染”到运动模糊纹理中。布尔标志指定是先渲染上一帧还是不渲染(参见背景点)。
  3. void ShowMotionBlurTexture(); - 就像一个刷新过程,它将最终结果显示在屏幕上。

为了使效果更真实,混合使用了以下参数:GL_SRC_ALPHAGL_ONE_MINUS_SRC_ALPHA。因为应用程序使用了 alpha 混合,通过改变上一帧的 alpha 值可以轻松改变效果的强度。

在演示应用程序中,可以使用以下按键:

  • 's' - 用于更改渲染的场景。
  • 't' - 用于更改传递给 RenderToMotionBlurTexture 过程的 FirstRenderTexture 标志。
  • 'w' - 用于线框渲染。
  • 'm' - 用于启用或禁用运动模糊。
  • 按 'a' 然后 '+' 或 '-' 调整 alpha 强度。

请注意,演示程序使用 GLUT 运行。

关注点

这种方法非常有用的,尤其是当进行全场景运动模糊时。如果此方法仅用于单个对象,则建议使用遮罩。

© . All rights reserved.