Catlantean 3D: モダンなツールを用いた1993年当時のグラフィックスの再現
モダンな環境におけるレトロな制約
Catlantean 3Dは、現代のコンパイラやプラットフォーム抽象化レイヤーを活用しつつ、1990年代初頭のゲームの技術的制限を再現するために開発された一人称視点シューティングゲーム(FPS)です。このプロジェクトは、本物のレトロな美学と決定論的な動作を確保するために、厳格に自己課した制約に従っています。
主な技術的制約は以下の通りです:
- 解像度と色: 目標解像度は320x240で、256色の限定されたパレットを使用します。
- レンダリングとオーディオ: すべてのレンダリングとサウンドミキシングは、ゼロから手動で実装されています。
- 決定論: プラットフォーム間での一貫した動作を保証するために、ゲームロジックには固定小数点演算が使用され、浮動小数点演算はレンダリング専用に予約されています。
- 抽象化: プラットフォーム抽象化レイヤーは、基本的なフレームバッファへのアクセス、キーボード/マウス入力、オーディオバッファへの書き込み、およびファイルシステムI/Oに限定されています。
パレットベースのレンダリングとライティング
VGA時代のゲームのような「鮮明な」外観を実現するために、Catlantean 3Dは、各ピクセルが256色パレットのインデックスとなる単一バイトの線形フレームバッファを使用します。画面上のすべてのピクセルが利用可能な256色のいずれかでなければならないため、このアプローチには慎重な色の選択が必要です。
カラーマップ・ライティング・システム
従来のレイキャスティングは、しばしば平坦なライティングになりがちです。現代のシェーダーのオーバーヘッドなしに奥行きを生み出すために、Catlantean 3Dはカラーマップ(高速なO(1)ライティング・ルックアップに使用されるパレット・インデックスの2D行列)を実装しています。
カラーマップのプロセスは以下の通りです:
- 線形化: 256色のパレットを線形な行として扱います。
- シェード生成: 各色に対して、31個のより暗いバリエーションが事前計算されます。システムはOklab色空間とその知覚的距離公式を使用して、パレット内の最も近い一致する色を見つけ、ユークリッド距離でよく見られる「冷たい」またはグレーに寄った外観を回避します。
- 色相シフト: 視覚的な魅力を高めるために、色が暗くなるにつれて、わずかに暖かい色相へとシフトさせます。
- 実行時ルックアップ: レンダラーはカメラからの距離に基づいてシェード・インデックスを計算し、カラーマップ行列から暗くなったパレット・インデックスを取得します。
パフォーマンスを最適化するために、カラーマップの行インデックスは、壁の場合は画面の各列に対して1回、床の場合は画面の各行に対して1回、およびスプライトに対して1回のみ計算されます。
アセット作成パイプライン
Catlantean 3Dのアセットは、プリレンダリング、手描き、およびプロシージャル生成の3つのカテゴリに分けられます。
プリレンダリング・スプライト
複雑なアニメーションの反復作業を効率化するため、3DモデルはBlenderで作成およびリギングされます。これらは、BlenderのAPIを活用するPythonスクリプトを使用してテクスチャにレンダリングされます。ダウンスケーリングによる「ぼやけ」を防ぐため、開発者はBlenderのコンポジット・ノードを使用して、画像をPythonスクリプトによるOklabベースのパレット量子化に渡す前にコントラストと鮮明さを高めます。
手描きアートとピクセルの整合性
ステータスバーの顔やHUDなどの特定の要素は、感情表現と明瞭さのためにAsepriteで手描きされます。このプロジェクトの重要なルールは、一貫したピクセル・スケールを維持することです。すなわち、1つのワールド・ユニットは64ピクセルに相当します。これにより、異なる解像度の資産が混在して視覚的な違和感が生じるのを防ぎ、これは低品質なインディー・タイトルによく見られる問題です。
プロシージャル生成と「ギビング(Gibbing)」
繰り返しの摩耗や汚れのテクスチャには、Pythonスクリプトがハイトマップ、ノイズマップ、およびグライム・マップを使用して最終的なテクスチャを生成します。 「ギビング(Gibbing)」(敵の死亡アニメーション)には、より複雑なプロシージャル・パイプラインが使用されます:
ボロノイ分解: スプライトは、ランダムなシード・ピクセルに基づいてパーティション分割されます。
創傷部からの出血: 幅優先探索(BFS)がチャンクの境界から内側に向かって広がり、パレットで定義された血液のランプ(ramp)に向かって色をブレンドします。
物理シミュレーション: 各チャンクには、重心、速度、回転、および重力が発生し、実行時の衝突検知なしに爆発をシミュレーションレーションします。
カスタム・ツールによるマップ・エディタ
一般的なツールであるTiledが、ライト・レベルの描画や特定のセル・フラグの機能にネイティブ・サポートをなかったため、開発者はwxPythonを使用してカスタム・マップ・エディタをビルドしました。
このエディタは、pybast(pybind経由でC++エンジン内部へのPythonバインディング)というライブラリを使用してエンジンと統合されており、エディタはゲーム・データのアーカイブやテクスチャを直接読み取ることが可能です。これにより、マップ・エディタが開発プロセスにおける第一級のオブジェクトとして開発され、コミュニッチューン・モッディング(コミュニティ・モッディング)を可能にするためにゲームと共に配布されるエコシステムが作成されます。
コミュニティの洞察と技術的背景
プロジェクトに関する議論は、使用されている制約が歴史的な意義を持つことを強調しています。コントリビューターたちは、オリジナルのVGA Mode 13h (320x200) が非正方形ピクセルを使用していたのは、64,000バイトのバッファが16ビット・セグメントに完璧に収まり、初期のCPUにおけるアドレス指定を簡ック化するためであったと指摘しています。
他の開発者は、Catlantean 3Dが使用しているレイキャスティング・エンジンは、壁の角度がより柔軟で高さが変化するDoomのBSPベースのエンジンよりも、Wolfenstein 3D(垂直な壁、一定の床・天井の高さ)に似ていると観察しています。}