当 Niels Leenheer 在浏览器中用数千个 <div> 元素完整渲染出经典游戏 DooM 时,他不仅完成了一个令人惊叹的技术演示,更为前端工程师提供了一份关于 CSS 渲染引擎极限能力的珍贵实验报告。这个名为 cssDOOM 的项目揭示了现代浏览器在实时 3D 场景下的能力边界,其工程经验对理解前端性能优化具有重要的参考价值。
渲染架构:JavaScript 与 CSS 的职责分离
cssDOOM 的核心设计理念是将游戏逻辑与渲染层严格分离。JavaScript 仅负责游戏循环和状态管理,包括玩家移动、碰撞检测、敌人 AI 和物品交互;而所有的视觉呈现工作 —— 从 3D 投影计算到精灵动画 —— 完全由 CSS 完成。这种分离方式使得项目能够充分发挥 CSS 引擎的计算能力,同时保持代码架构的清晰性。
在具体实现层面,每个墙体、地板和精灵都是独立的 DOM 元素,通过 CSS 3D 变换进行空间定位。项目使用原始 DooM WAD 文件中的几何数据:顶点、线段定义、边定义和扇区信息。JavaScript 将这些原始坐标作为自定义属性注入 DOM,CSS 则利用 calc()、hypot() 和 atan2() 等数学函数完成所有几何计算。例如,墙体的宽度通过勾股定理计算,旋转角度通过反正切函数确定,整个过程不需要 JavaScript 逐帧干预。
关键 CSS 技术在极限场景中的应用
项目深度依赖了多个现代 CSS 特性。@property 声明是整个渲染系统的基石,它允许自定义属性获得类型信息,从而使 --player-z 这类数值属性能够支持过渡和动画。当玩家从高处落下时,平滑的坠落过渡效果正是通过注册自定义属性为 <number> 类型实现的,否则浏览器只会将其视为字符串而无法进行数值插值。
纹理贴图的无缝拼接是另一个技术难点。相邻扇区共享相同地板纹理时,必须保证贴图在边界处连续。项目通过使用世界坐标作为 background-position 的偏移量,确保所有扇区共享同一个纹理网格,无论各个 <div> 元素位于何处。这种技术对大规模场景渲染具有重要启示:统一坐标系统可以避免元素级别的重复计算。
精灵的公告板效果通过 rotateY() 实现,使 2D 图像始终面向摄像机。行走动画则利用 background-position-x 配合 steps() 函数实现帧切换。当敌人开始攻击或死亡时,JavaScript 只需修改 data-state 属性,CSS 便会自动切换到不同的精灵图区域。整个动画状态机完全由 CSS 驱动,JavaScript 无需跟踪帧数。
性能瓶颈与工程妥协
尽管 CSS 展现了惊人的计算能力,但实时游戏场景暴露了浏览器渲染引擎的显著局限。项目遇到的首要问题是浏览器不会自动剔除视锥体外的元素。浏览器 compositor 被设计用于处理分层的平面 UI,而非数千个 3D 表面,因此必须手动实现剔除逻辑。
Leenheer 开发了两种剔除策略。第一种是传统的 JavaScript 方案:每隔几帧检查每个元素与摄像机的距离和朝向角度,将不可见元素设置为隐藏状态。第二种是实验性的纯 CSS 剔除方案,利用 CSS 动画的 animation-delay 技巧间接控制 visibility 属性。这种被称为「类型研磨」的技术通过设置负延迟使动画跳转到特定帧,从而在「可见」和「隐藏」状态间切换。随着 CSS if() 函数的普及,未来可以实现更优雅的条件渲染。
浏览器兼容性方面存在多个已知问题。Safari 的 View Transitions 会完全压平所有 preserve-3d 场景,导致 3D 世界在过渡期间变成平面图像。通过 CSS 自定义属性设置 background-image 会触发严重的性能回退,因为浏览器在每一帧都会重新解析所有 var() 引用,导致数千个纹理元素被重复光栅化。解决方法是直接使用内联样式设置背景图。Chrome 的 compositor 在处理大量 3D 变换表面时存在稳定性问题,游戏中偶尔会出现纹理消失的现象。
更大的挑战来自移动端。Safari on iOS 在元素过多时会直接崩溃,这迫使项目必须在功能完整性与运行稳定性之间做出取舍。对于大规模前端应用而言,这一问题提醒我们:DOM 数量不仅影响性能,更可能导致浏览器进程终止。
工程化启示
cssDOOM 项目为前端性能优化提供了若干可落地的工程建议。首先,DOM 规模必须受到严格控制 —— 该项目在复杂地图下会达到数千个元素,这对任何前端应用都是极高的负载。其次,现代 CSS 数学函数已经足够强大,可以在不借助 JavaScript 的情况下完成复杂的几何计算,但前提是数据流设计必须遵循从 JavaScript 到 CSS 的单向原则。第三,对于 3D 场景,自定义剔除策略往往是必要的,因为浏览器的自动优化主要针对传统页面布局设计。
在技术选型层面,该项目证明了一个重要观点:CSS 能够承担实时渲染任务,但其适用场景应限于 UI 复杂度高而帧率要求相对宽松的交互界面。对于需要稳定 60 帧的沉浸式 3D 体验,WebGL 或 WebGPU 仍然是更合适的选择。CSS 的优势在于其声明式特性和开发效率,而非原始渲染性能。
资料来源
本文核心技术与性能数据来源于 Niels Leenheer 在个人博客发布的详细技术分析文章「CSS is DOOMed」以及其开源的 cssDOOM 项目代码仓库。