最近我为我的引擎制作了一个动画,展示了每个像素渲染一个帧的过程,我觉得这个过程可能会很有趣。首先,我的渲染器是一个自定义的CPU扫描线器。所以,所有draw{..}例程,最终都会写入一个颜色缓冲区(然后由SDL呈现到显示器上)。这是非常方便的,因为对于一个给定的帧,每个这样的位置在代码中只需要生产一个新的图像,基于之前绘制的像素的图像,依此类推。我的缓冲区是320x180,所以我需要>57600张图像(是的,这是一个非常大的数据量)。想法是,在游戏中按下一个按钮,等待所有像素都写入自己的图像到磁盘上。然后游戏继续正常进行。
- 首先,我们定义一个全局的帧计数器。我们需要这个来命名图像(btw,Rust使这个变得有点痛苦)。有其他方法,但这个方法很快又很脏。
- 然后,在每个位置,一个像素写入颜色缓冲区,我们做:
- 加载图像“frame_current_frame.ppm”在.ppm格式下。它需要一些头部解析等等来达到数据。这张图像最初会是黑色的,因为写入缓冲区的清除()函数也重置了计数器。
- 计算缓冲区的线性索引并写入新像素值
- 保存一个新的图像“frame_++current_frame.ppm”,一起保存其头部数据
- 如果所有都顺利的话,我们会在选择的目录中得到一个大量(至少)的图像。它们可能会超过57600张,因为一些像素会被写入多次,因为透明对象和重叠对象(引擎使用典型的z缓冲区)。
- 然后使用ffmpeg将图像组合起来,得到最终视频,选择一个合适的帧率。注意这里,很多像素会被跳过,以保持60fps和<2分钟的视频长度。如果我们想保留所有像素并在60fps下呈现它们,视频长度会更长。
注意1:视频压缩艺术品破坏了个别帧,所以图像中的许多位置似乎会随时间而改变。显然它们不会。
注意2:游戏使用渲染到纹理来绘制世界空间的HUD/驾驶舱。但是这里得到的只是几条三角形的结果。要得到实际渲染到纹理的三角形在动画中,我需要进行几个大修改(例如,你不知道最终的纹理位置,所以你无法在其位置上动画它),或暂停主动画并在一边动画那些部分。我没有费心。
注意3:捕获过程需要很多时间,所以游戏会在读取和写入期间短暂地冻结。这比我想象的要容易得多,主要是因为渲染器,所有像素写入都是明显的和可访问的。没有触摸渲染代码,只做了一个快速的修复,花了半小时。以下是结果视频:https://www.youtube.com/watch?v=yXZk3tt6gPw
评论 (0)