Mode 7
Mode 7は、スーパーファミコン(SNES)で背景レイヤーを回転・拡大縮小・投影変換するグラフィック機能。
2Dグラフィックを擬似的に3D空間のように表現し、当時のゲーム(F-ZERO、マリオカートなど)に奥行き感や高速な視点移動をもたらした重要な技術です。
主な特徴と効果
- 回転と拡大縮小
- 背景の1レイヤーに対して自由な回転とスケーリングをスキャンライン単位で実行可能。
- 擬似3D表現
- 背景を水平面として描写し、奥のものを小さく、手前のものを大きくすることでパースペクティブ(遠近法)を再現。
- テクスチャマッピング
- 2D画面を3D空間に見せるため、床面にテクスチャ(画像)を貼り付けたような効果を生成。
- 歴史的背景
- 1990年代初頭のスーパーファミコンの看板技術であり、任天堂のライバル機に対する強力な強みとなった。
- 主にレースゲーム(マリオカート、F-ZERO)やシューティングゲーム(スターフォックスなど)の舞台となる地面の描写に使用された。
- 技術的な詳細
- スキャンラインベースの処理により、各行の描写ごとにパラメータ(行列)を変化させることで、複雑な回転・拡大縮小を1画面内で組み合わせる。
- 特殊な構造: 256色の背景レイヤーを回転・縮小し、VRAM上に1024x1024ピクセルのタイルマップとして管理。
Playdateにおける "Mode 7" の実装方法
Playdateの1ビット画面と限られたCPUリソース(Cortex-M7)で、スーパーファミコンの「Mode 7」のような擬似3D背景を実装する場合、「水平スキャンラインごとの
アフィン変換」と「テクスチャの水平スライス」が現実的なアプローチになります。
Playdateにはハードウェアによる
スプライトのスケーリングや回転の支援はありますが、背景レイヤー全体を3D投影する専用機能はないため、ソフトウェア側で工夫が必要です。
1. 基本的なレンダリングの仕組み
Mode 7の視覚効果は、2Dのタイルマップを遠近法(パースペクティブ)に基づいて変形させることで実現します。画面上の各行(スキャンライン) y方向 に対して、以下の手順を適用します。
- 1. 距離(スケール)の計算
- 画面下部ほど自機に近く(拡大)、上部ほど遠い(縮小)ため、行ごとに垂直方向のスケール $z$ を算出します。
- 2. テクスチャ座標の決定
- 算出した "z" に基づいて、ソース画像(背景タイルマップ)からサンプリングする座標の開始点と移動ベクトルを求めます。
- 3. 描画
- 1行分のピクセルを画面に転送します。
2. Lua SDK での実装:水平スライス法
Luaでピクセル単位のループを回すと処理落ちするため、画像を「1ピクセル高さの横長スライス」として扱い、SDKの drawSampledBitmap や drawWithTransform を利用するのが効率的です。
実装手順は以下の通りです。
- 画像の分割
- 背景となる大きな画像を、1ピクセル高さの `playdate.graphics.image` の配列として保持します。
- スキャンラインごとの描画
- 画面の Y座標ごとに、その行が表現する「擬似的な奥行き」を計算します
- playdate.graphics.drawSampledBitmap を使い、ソース画像の特定行をスケーリング・オフセットして描画します
-- 擬似コードのイメージ
for screenY = horizon, displayHeight do
local z = focalLength / (screenY - horizon)
local width = textureWidth * z
local xOffset = (displayWidth - width) / 2 + scrollX * z
-- 特定の行(スライス)を拡大縮小して描画
imageSlices[textureY]:drawSampled(xOffset, screenY, width, 1)
end
3. C SDK での実装:直接バッファ操作
最高のパフォーマンスを求めるなら、C言語による直接的なフレームバッファ操作が推奨されます。
- 固定小数点演算の活用
- PlaydateのCPUは浮動小数点演算も可能ですが、スキャンライン内のピクセルループでは固定小数点(Fixed-point)を使用することで、演算コストを最小限に抑えられます。
- インクリメンタルな座標更新
- 各ピクセル "x" において、テクスチャ座標 "(u, v)" を以下の形式で更新します。
- u_{x+1} = u_x + du
- v_{x+1} = v_x + dv
- ここでの "du, dv" はその行における回転とスケールに基づく定数です。
4. Playdate特有の最適化と制約
PlaydateでMode 7を「らしく」見せるためのテクニックです。
- 1ビット画面とディザリング
- 遠くの景色が単色で塗りつぶされると距離感が失われます。
- 距離 "z" に応じてディザリングのパターン(playdate.graphics.setDitherType)を切り替えると、1ビットでも擬似的な霧(フォグ)やグラデーションを表現でき、奥行きが強調されます。
- ルックアップテーブル(LUT)の利用
- "1 / z" の計算や "sin/cos" の計算は重いため、あらかじめ配列に計算結果を格納しておく(LUT化する)ことで、実行時の負荷を大幅に削減できます。
- クランク(Crank)との連動
- クランクの回転角をアフィン変換行列の回転パラメータ(θ)に直接代入することで、F-ZEROのような急旋回操作を直感的に実装できます。
推奨される学習リソース
Playdateコミュニティでは、この種の手法を「Mode 7-style scaling」や「Pseudo-3D floor」と呼びます。SDKに同梱されているサンプルコードや、GitHub上の Playdate-Samples にある描画最適化の例を参考にすると、実装のヒントが見つかりやすいはずです。
関連ページ
最終更新:2026年05月04日 15:24