世界を動かす技術を、日本語で。

CSSは運命にある

概要

  • CSS のみで DOOM のレンダリングを実現した技術解説
  • 3D空間 での配置や計算を CSSカスタムプロパティ関数 で処理
  • ゲームロジック はJavaScript、 描画 はCSSが担当
  • DOOM座標系CSS 3D座標系 の変換・工夫
  • アニメーションテクスチャ の工夫も紹介

CSSでDOOMを構築した理由と経緯

  • CSSの進化 を体感・証明するためのプロジェクト
  • 壁・床・オブジェクト すべてを <div> で表現、 CSS transforms で3D配置
  • ゲームロジック はJavaScript、 描画処理 はCSSのみで完結
  • 限界への挑戦ブラウザの可能性の追求
  • Github でソースコード公開

技術的なアプローチ

  • DOOMのオリジナルデータ (頂点・ライン・セクター等)を抽出・利用
  • 各壁・床DOOM座標 をカスタムプロパティとして付与
  • 3D変換・幅・回転角 などは CSS関数 (hypot(), atan2()等)で計算
  • JavaScript はWADデータの受け渡しとゲームループのみ担当
  • CSS が三角関数・幾何計算を担う分業体制

DOOM座標系とCSS 3D座標系の対応

  • DOOM座標系 :Y軸が北方向に増加する2Dシステム
  • CSS 3D座標系 :Y軸が上方向、Z軸が手前方向
  • translate3d(x, -z, -y) で座標を変換
  • rotateY(atan2(Δy, Δx)) で壁の回転を自然に実装
  • 座標変換の最小化 でシンプルな実装

カメラの代わりに世界を動かす手法

  • CSSにはカメラ機能がない ため、 プレイヤーの移動=世界の反転移動
  • --player-x, --player-y, --player-z, --player-angle の4つのカスタムプロパティで管理
  • #scene に対して transform で逆方向に移動・回転を適用
  • perspective 補正のために translate: 0 0 var(--perspective) を追加
  • 移動・視点変更 は4つの値を更新するだけで完結

床・天井の表現とクリッピング

  • 床は<div>をrotateX(90deg) で水平に配置
  • clip-path: polygon() で多角形・不規則な形状にカット
  • clip-path: path()evenodd で穴あきや複雑な床も表現
  • shape() の利用でパス定義を自然言語的に記述可能
  • SVGパス による柔軟なクリッピング

テクスチャのタイル・整列

  • 隣接セクター間のテクスチャ連続性 を確保
  • background-position にワールド座標を使用し、全体で一貫したパターン
  • <div>の配置座標 に応じてテクスチャ基点を調整
  • background-size/repeat でDOOMらしいタイル表現

ドアやリフトのアニメーション

  • ドア開閉<div>transformtransition で滑らかにアニメーション
  • state属性 の切り替えでCSSアニメーションを制御、JavaScriptループ不要
  • リフト では --player-z も連動して更新、プレイヤーの上下移動を実現
  • @property でカスタムプロパティを型登録し、スムーズなトランジションを可能化
  • JavaScriptとCSSアニメーション の同期で自然な動きを演出

まとめ:CSSの可能性と今後

  • ゲームレンダリング がCSSのみで実現可能な時代
  • CSS関数・カスタムプロパティ・clip-path 等の進化が鍵
  • JavaScriptは最小限CSSが主役 の新しいWeb表現
  • CSSの限界を探る実験的プロジェクト としての価値
  • 今後のCSS進化 とWeb表現の未来への期待

Hackerたちの意見

この調子だと、すぐにハッカーたちが電卓や電子レンジでCrysisを動かそうと挑戦するようになるかもね。

AIが人間でDoomを動かそうとする時代が来るんじゃないかな。

CSSで3Dシーンを作るのは昔から可能だったけど、このプロジェクトみたいにインタラクティブにするにはJavaScriptが必要だった。でも今はCSSの機能がもっと増えてる。昔はCSSでチューリング完全にするには人間がチェックボックスをクリックしなきゃいけなかったけど、今はJavaScriptなしで、ユーザーの操作もいらずにCPU全体をエミュレートできるようになったんだ。だから、DOOMもリアルタイムで純粋にCSSでできるんじゃないかって思う。[0]: https://keithclark.co.uk/labs/css-fps/ [1]: https://lyra.horse/x86css/

作者はCSS x86プロジェクトにリンクしてるね: > そう、Lyra RebaneはCSSで完全にx86 CPUを作ったけど、その技術はゲームループを処理するには速すぎないんだ。だから、結果的にたくさんのJavaScriptを使うことになってる。

でも、ブラウザでどうやって試せるの? 編集: https://cssdoom.wtf/

携帯でDoomを試したことなかったけど、これ意外とスムーズでめっちゃ遊べるね。

Firefoxではスムーズに動くよ。ただ、デフォルトのキー設定が壊れてて、Altを押すとメニューが開いたり閉じたりしちゃう。あと、Alt + 左矢印でゲームが終了して、履歴に戻っちゃう。面白いことに、Chromiumではもっとカクカクしてた。横に動くためのキーが見つからなかったし(「ストレイフ」ね)。全体的に、かなり驚きだわ。

モバイルのSafariでは完璧に動くよ。こんなの初めてだわ。

世界を動き回り始めたら、スマホがすぐに熱くなったよ :')

最近のCSSは実験的な機能を通じて、完全なプログラミング言語に近づいてきてるよ。例えば、2025年にはif文やモジュロみたいな数学関数が追加されたんだ。https://www.simplethread.com/new-and-upcoming-css-features-i...

本当に欠けてるのは、実際のプログラミング言語の使いやすさだね。

2006年にArs Technicaがエイプリルフールの記事を出して、ずっと待たれていたDuke Nukem Foreverがついに登場するって言ってたんだよね…ブラウザゲームとして!ホント、面白いよね。ここまで来たのを見るのは信じられない。

Quake Liveはその約1年後にブラウザのNaClゲームとして出たよね。

本当にすごい、特にビューポートのカリングトリックは見たことなかった。ちなみに、要素を検査したいなら、ビューポートのdivがマウス要素を消費しちゃうから、これを#viewport { pointer-events: none; } #viewport * { pointer-events: initial; }で消せるよ。

これ最高だね。Firefoxも評価されるべきだよ、最もスムーズに動いて、必要な回避策が少ないから。

すごいね!ボーナスとして、divを削除するだけで壁抜けできちゃう、あはは。

全く同感だよ…特にStitch 2みたいなプラットフォームが、非技術者でもかなり良いUI/UX体験を得られるように障壁を取り除いてるのが素晴らしい。

サーバーで計算されたシンプルな絶対レイアウトを試してみたんだけど、めっちゃ助かってる。1) リフローがない 2) 例外がほとんどない 3) LLMには超簡単