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() 功能吗?