概要
- Game Boy Color でリアルタイム画像レンダリングを実現した自作ゲームの技術解説
- Blender を用いた3Dワークフローとノーマルマップ生成手法
- 球面座標系 と ログ演算・テーブル参照 による高速化
- 自己書き換えコード など、ハードウェア制約下での最適化手法
- 実際の パフォーマンス測定 と工夫点のまとめ
Game Boy Color向けリアルタイム3Dライティングゲーム制作デモ
- Game Boy Color 上でリアルタイムに画像をレンダリングするゲームの開発
- プレイヤーは 軌道上の光源 を操作し、オブジェクトを回転させる体験
- GitHub でコード・ROMファイルを公開
- nukep/gbshaderにてソースコード・ROMダウンロード可能
3DワークフローとBlenderでのLookdev
- Blender で事前にビジュアルを検証し、プロジェクト開始判断
- 擬似ディザリング を法線ベクトルにランダムベクトルを加える方法で表現
- ノーマルマップ生成には Cryptomatte やカスタムシェーダを活用
- 特定色の維持や画面部分の合成に利用
ノーマルマップとシェーディングの数理
- ノーマルマップは ベクトル場 として機能
- RGB = XYZ でベクトル情報をエンコード
- Lambertシェーダ はドット積計算で表現
- ( v = N \cdot L )(N: 法線, L: 光ベクトル)
球面座標系による高速ドット積
- 球面座標 (r, θ, φ)を使い、計算量削減
- 法線・光源ともに単位ベクトルと仮定し半径1で簡略化
- ( v = \sin N_\theta \sin L_\theta \cos(N_\varphi - L_\varphi) + \cos N_\theta \cos L_\theta )
Game Boy Colorでの実装と最適化
- Lθ (光源のθ)は定数化し、 Lφ (光源のφ)をプレイヤーが操作
- 各ピクセルは (Nφ, log(m), b) の3バイトでエンコード
- log(m) を使う理由は、Game BoyのCPUが乗算・浮動小数点非対応のため
- 加算・乗算 は全て ログ空間 + ルックアップテーブル で処理
- 負数対応のため符号ビットをMSBにエンコード
- 8ビット分解能で-1.0~+1.0を表現
コア計算式とルックアップテーブル
- コア計算: ( v = m \cos(N_\varphi - L_\varphi) + b )
- 実装上は ( v = pow(m_{log} + cos_{log}(N_\varphi - L_\varphi)) + b )
- 1ピクセルあたり
- 減算1回
- cos_log参照1回
- 加算1回
- pow参照1回
- 加算1回
- 合計: 加減算3回、テーブル参照2回
パフォーマンスと最適化
- 1フレームで 15タイル (960ピクセル)処理
- 1ピクセル約130サイクル、空行は3サイクル
- 1フレームの約 89% をレンダリングに使用
- 自己書き換えコード による高速化
- 可変数値処理を命令書き換えで高速化
- 1ピクセルごとに12サイクル削減、全体で約10%短縮
まとめ
- レトロハードウェア の制約下での創意工夫
- ログ演算・テーブル参照・自己書き換えコード活用
- 現代的な3Dワークフロー と 低レベル最適化 の融合
- GitHub でソース・ROM公開、技術的な参考資料としても有用
参考リンク
- ソースコード・ROM: https://github.com/nukep/gbshader