跳转到内容

OpenGL 编程/运动模糊

来自维基教科书,开放世界中的开放书籍
正常。
运动模糊。

除了颜色、深度和模板缓冲区,大多数显卡还提供所谓的累积缓冲区。本质上它们是每个颜色精度为 16 位或更高的颜色缓冲区。但是,无法直接绘制到累积缓冲区。相反,只有少数操作可以一次对整个累积缓冲区执行。

  • glAccum(GL_LOAD, value):将普通颜色缓冲区的内容乘以 value 复制到累积缓冲区。
  • glAccum(GL_RETURN, value):将累积缓冲区的内容乘以 value 复制到颜色缓冲区。
  • glAccum(GL_ACCUM, value):将普通颜色缓冲区的内容乘以 value 添加到累积缓冲区。
  • glAccum(GL_ADD, value):将 value 添加到累积缓冲区中的所有像素。
  • glAccum(GL_MULT, value):将累积缓冲区中的所有像素乘以 value

在所有情况下,value 都是一个浮点数。这些函数可以轻松地计算多个帧的(加权)总和或平均值。在本教程的第一部分,我们将看到如何利用它轻松地将运动模糊添加到几乎任何 OpenGL 程序中。

运动模糊

[编辑 | 编辑源代码]

运动模糊发生在物体移动速度过快(相对于相机),或者相机的曝光时间过长,以至于在曝光过程中,某些物体移动了超过半个像素,因此看起来模糊了。运动模糊通常不希望发生,但在使用真实相机时有时很难避免,因为曝光时间在很大程度上取决于场景中的光量。光线越少,曝光时间越长,运动模糊的效果越强。这是户外用摄像机拍摄的视频“感觉”与用同一台摄像机在室内拍摄的视频不同的原因之一。

模拟运动模糊

[编辑 | 编辑源代码]

使用累积缓冲区实际上很容易创建运动模糊效果。OpenGL 应用程序通常的工作方式如下

while(true) {
  do_time_evolution(timestep);
  draw_scene();
  glSwapBuffers();
  wait_until_next(timestep);
}

其中函数 do_time_evolution() 负责更新场景中移动物体的坐标,以及/或者摄像机本身的移动。绘制完场景后,它会使用 glSwapBuffers() 显示在屏幕上,并且可以选择等待一段时间来限制帧率。为了添加运动模糊,您可以多次使用更小的时间步长绘制场景,并且只显示这些场景的平均值

int n = <number of frames to accumulate>
int i = 0;

while(true) {
  do_time_evolution(timestep / n);
  draw_scene();

  if(i == 0)
    glAccum(GL_LOAD, 1.0 / n);
  else
    glAccum(GL_ACCUM, 1.0 / n);

  i++;

  if(i >= n) {
    i = 0;
    glAccum(GL_RETURN, 1.0);
    glSwapBuffers();
    wait_until_next(timestep);
  }
}

通过累积大量帧可以获得最佳效果,但很快就会受到 GPU 性能的限制。最好将要累积的帧数设置为可配置的,或者尝试自动确定在一个完整的 timestep 内可以渲染多少帧。

  • 将运动模糊添加到任何以前的教程中。更有趣的是迷你传送门和 glescraft,您可以在其中四处走动。
  • 如果您要将后期处理效果添加到场景中,您应该在应用运动模糊之前还是之后进行此操作?
  • 如果您的 GPU 没有提供累积缓冲区,您可以通过渲染到纹理来重新创建 glAccum() 功能吗?
华夏公益教科书