Catlantean 3D: 使用現代工具重現 1993 年時代風格的圖形

在現代環境中的復古限制

Catlantean 3D 是一款第一人稱射擊遊戲,旨在複製 1990 年代初期的遊戲技術限制,同時利用現代編譯器和平台抽象層。該專案遵循一套嚴格的自我限制,以確保真實的復古美學和確定性行為。

核心技術限制包括:

  • 解析度與色彩: 目標解析度為 320x240,並使用 256 色有限調色盤。
  • 渲染與音訊: 所有渲染和聲音混音都是從零開始手動實現的。
  • 確定性: 遊戲邏輯使用定點數運算以保證跨平台的行為一致性,而浮點數運算則保留給渲染使用。
  • 抽象化: 平台抽象層僅限於基本的幀緩衝區存取、鍵盤/滑鼠輸入、音訊緩衝區寫入以及檔案系統 I/O。

基於調色盤的渲染與光照

為了實現 VGA 時代遊戲那種「清晰」的外觀,Catlantean 3D 使用線性幀緩衝區,其中每個像素都是一個單一字節,用於索引至 256 色調色盤。這種方法需要深思熟慮的色彩選擇,因為螢幕上的每個像素都必須是 256 種可用顏色之一。

色彩映射光照系統

傳統的投射法(raycasting)往往會導致光照扁平化。為了在不增加現代著色器開銷的情況下創造深度感,Catlantean 3D 實現了一個色彩映射(colormap)——一個用於快速、O(1) 光照查找的調色盤索引 2D 矩陣。

色彩映射的處理流程如下:

  1. 線性化: 將 256 色調色盤視為一個線性行。
  2. 陰影生成: 為每種顏色預先計算 31 種較暗的變體。系統使用 Oklab 色彩空間及其感知距離公式,在調色盤中尋找最接近的匹配顏色,從而避免了使用歐幾里得距離時常見的「冷色調」或灰色偏移現象。
  3. 色調偏移: 隨著顏色變暗,會應用輕微的暖色調偏移,以提升視覺吸引力。
  4. 執行期查找: 渲染器根據與攝影機的距離計算陰影索引,並從色彩映射矩陣中檢索較暗的調色盤索引。

為了優化效能,牆壁的色彩映射行索引在每個螢幕列僅計算一次,地板的行索引在每個螢幕行僅計算一次,而精靈圖(sprite)則每個計算一次。

資產建立流程

Catlantean 3D 的資產分為三類:預渲染、手繪以及程序化生成。

預渲染精靈圖

為了簡化複雜動畫的迭代過程,3D 模型是在 Blender 中建立並進行骨架綁定的。這些模型使用利用 Blender API 的 Python 腳本渲染成紋理。為了防止縮放時產生的「模糊」感,開發者使用 Blender 的合成節點來增加對比度和清晰度,然後將圖像通過 Python 腳本進行 Oklab 為基礎的調色盤量化

手繪藝術與像素一致性

某些元素,例如狀態欄面部和 HUD,是在 Aseprite 中手繪的,以確保情感表達和清晰度。該專案的一個關鍵規則是維持一致的像素比例:一個世界單位等於 64 像素。這可以防止不同解析度的資產混合時產生的視覺突兀感,這是低品質獨立遊戲中常見的問題。

程序化生成與「肢解」效果

對於具有重複磨損和污垢感的紋理,Python 腳本使用高度圖、雜訊圖和污垢圖來生成最終紋理。對於「肢解」(gibbing,敵人死亡動畫)使用了更複雜的程序化流程:

  1. Voronoi 分解: 精靈圖根據隨機種子像素被分割成塊狀物。
  2. 傷口流血: 一個廣度優先搜尋(BFS)從塊狀物邊界向內擴散,將顏色混合向調色盤定義的血液漸層。
  3. 物理模擬: 每個塊狀物被分配一個質心、速度、旋轉和重力,在不需要執行期碰撞檢測的情況下模擬爆炸效果。

自定義工具與地圖編輯

由於 Tiled 等通用工具缺乏對光照等級繪製和特定單元格標記(cell flags)的原生支持,開發者使用 wxPython 構建了一個自定義地圖編輯器。

這個編輯器透過一個名為 pybast 的函式庫(透過 pybind 將 C++ 引擎內部進行 Python 綁定)與引擎整合,允許編輯器直接讀取遊戲數據存檔和紋理。這建立了一個緊密的生態系統,使地圖編輯器成為開發過程中的一等公民,並將隨遊戲發佈,以供社群群眾模組化(modding)。

社群觀點與技術背景

圍繞該專案的討論突顯了所使用的限制條件的歷史意義。貢獻者指出,原始的 VGA Mode 13h (320x200) 使用非正方形像素,因為 64,000 位元組的緩衝區能完美契合 16 位元分段,從而簡化了早期 CPU 的定址。

其他開發者觀察到,nCatlantean 3D 使用的投射法引擎更接近 Wolfenstein 3D(垂直牆壁、恆定的地板/天花板高度)而非基於 BSP 的 Doom 引擎,後者允許更靈活的牆壁角度和變動高度。

Sources