为微型掌机打造微型 3D 渲染器

为微型掌机打造微型 3D 渲染器

Hacker News 摘要

原标题:Building a Tiny 3D Renderer for a Tiny Handheld

Cristina Ramos 分享了她为 Playdate 掌机开发 3D 软件渲染器的技术历程。Playdate 是一款性能有限、采用单色屏幕的掌机,开发者最初并不确定在该平台上实现 3D 效果的可行性。

初期测试与性能基准

为了测试设备的 3D 处理能力,开发者编写了一个简单的射线投射程序。这个测试主要用于评估浮点数运算、向量数学、内存操作以及屏幕绘制的速度。由于 Playdate 的屏幕分辨率低且是 1 位单色显示,内存开销较小,这为实现类似 3DO 或世嘉土星时代的 3D 效果提供了可能。

Playdate 没有内置的 GPU,所有 3D 渲染工作必须完全依赖 CPU 完成。这意味着开发者需要手动处理多边形顶点变换、投影、裁剪、排序、着色以及将像素写入帧缓冲,且必须保证足够的帧率以实现流畅游玩。

采用 BSP 地图格式

渲染器加载的是 Quake 的 BSP 地图文件。选择这种格式的原因有两个:

1. 开发者可以直接利用 TrenchBroom 和 ericw-tools 等成熟的关卡编辑器和编译工具,节省大量开发时间。

2. BSP 格式(二进制空间分割)通过预计算可见性集合(PVS)来优化渲染。在运行时,渲染器能快速剔除摄像机看不到的地图部分,大幅减轻 CPU 负担。

深度缓冲与纹理映射

开发者最初尝试使用从后往前绘制的画家算法,但最终决定加入 16 位倒数深度缓冲(z-buffer)。这种方式在靠近摄像机的地方精度更高,能有效解决物体遮挡问题,并简化了动态物体和透明纹理的处理。

在纹理映射方面,开发者放弃了仿射纹理映射(会导致纹理扭曲),而采用了透视校正纹理映射。为了平衡性能和效果,渲染器每隔几个像素计算一次完整的除法,中间像素则使用快速近似算法。

1 位显示器上的光照处理

Playdate 屏幕只有黑白两色,无法直接显示灰色。开发者通过抖动算法(Dithering)来模拟中间色调,使用 8x8 的拜耳矩阵根据亮度阈值决定像素是黑还是白。

为了避免图像过于混乱,开发者借鉴了《奥伯·丁的回归》和《街头涂鸦》的视觉风格,选择了单色赛璐珞着色效果。这种风格带有强烈的轮廓线和简单的纹理,极大地提升了画面的可读性和独特性。

针对 CPU 的深度优化

为了在 Playdate 上获得理想性能,开发者采取了多项优化措施:

编译器选项:针对 Cortex-M7 CPU 进行特定调优,启用硬浮点运算(Hard-float ABI)和激进的优化标志(-Ofast),并剔除不必要的二进制元数据。

指令集优化:使用 ARM Cortex-M7 汇编语言编写了自定义的 floor、ceil、sqrtf 和 fabsf 等浮点运算函数。

半分辨率渲染:内部渲染分辨率为 200x120,然后缩放到 400x240 的屏幕上。这是提升性能最显著的手段。

预计算与缓存:尽可能将计算工作移出游戏循环。

内存布局控制:使用宏将关键代码放置在特定的内存区域,以提高指令缓存命中率,并对频繁调用的小函数强制执行内联。

开发者总结认为,在 Playdate 上开发 3D 渲染器是一个不断尝试和 benchmark(基准测试)的过程。目前的渲染器虽然不完美,但已经足以支持游戏原型的开发,让这款名为 KATAVATIS 的第一人称水下类银河战士恶魔城游戏从构想变为现实。


原文:https://saffroncr.itch.io/katavatis/devlog/1534514/building-a-tiny-3d-renderer-for-a-tiny-handheld

评论:https://news.ycombinator.com/item?id=49010993

Report Page