Godot 4向けの3Dピクセルアートシェーダー
スプライトシートに焼き込めないものもあります。3Dのレベル全体、プレイヤーがどこへでも操縦する乗り物、100通りのポーズを持つボスなどです。PixorはそのルックをGodot 4のシェーダーとして書き出すので、これらもベイクしたキャラクターと同じピクセルでリアルタイムに描けます。


3Dゲームでピクセルアートにする2つの方法
Godotのゲームをピクセルアート風にする一般的な方法は2つあります。1つ目はベイクです。各キャラクターを全方向からスプライトシートにレンダリングし、AnimatedSprite2Dで再生します。2つ目は3Dシーンそのものを低解像度で描く方法で、ライトを帯状にし、色を制限し、輪郭線を描くシェーダーを通し、ニアレストフィルタで拡大します。「3D pixel art shader Godot」や「Godot 4 post processing pixel art」という検索が指すのは、2つ目です。
どちらにも出番があります。ベイクしたシートは手作りのコントロールと手直しができ、描くコストもかかりません。リアルタイムは、シートに収まらないものを扱えます。カメラが動き回るレベル、どの角度にも向きを変える車、すべてが同時に動くシーンなどです。問題は、この2つがあまり一致しないことです。スプライトは1つのパイプラインから出て、レベルは別に書かれたシェーダーから出るため、輪郭線、色、ライトが食い違います。
pxr shaderは、スプライトのベイクに使うのと同じスタイルからGodotのシェーダーを書き出して、これを解決します。
シェーダーを書き出す
モデルとルック、またはプロジェクトと、Godotプロジェクト内のフォルダを指定します。
pxr shader knight.glb --preset selout --size 64 -o my-game/pixor
pxr shader game.pixor -o my-game/pixor --res res://pixor
-oはディスク上のフォルダです。--resはGodotから見た同じフォルダで、res://のパスです。res://にフォルダ名が続く形でない場合に指定します。フォルダには5つのファイルができます。
| ファイル | 働き |
|---|---|
pixor_look.gdshader |
マテリアル。各ピクセルは、ベイクしたスプライトと同じように、自分の色のランプ、明暗の帯の段、ハイライトを、パレット自身の色で取ります。ライティングなし(unshaded)で、ルックがそのままライトです。 |
pixor_lines.gdshader |
線。スクリーンパスで、モデルの周りの空のピクセルにシルエットを、ある面が別の面の手前にある場所に内側の線を、スタイルの線の色で描きます。 |
pixor_view.tscn |
ピクセルグリッド。スプライトのサイズのビューポートをニアレストフィルタで4倍に拡大したもので、Pixorのカメラと線が入っています。 |
pixor_look.gd |
PixorLook.apply($Level)は、ノード以下のすべてのメッシュに、各マテリアルの色とテクスチャを保ったままルックを与えます。 |
pixor_shader.json |
サイズ、スケール、パレット、そしてスタイルのうちシェーダーが省くもの。 |
シーンに入れる
- フォルダをGodotプロジェクトにコピーするか、
-oで直接そこに書き出します。 pixor_view.tscnをメインシーンに追加します。これが入っている3Dの世界を、アウトラインパス付きでピクセルグリッド越しに描きます。- メッシュにルックを与えます。スクリプトからは、
PixorLook.apply($Level)でノード以下のすべてのメッシュにマテリアルが設定されます。手作業なら、メッシュのマテリアルにpixor_look.gdshaderを設定します。
ほかに設定するものはありません。明暗の帯、ランプ、パレット、線の色はシェーダーに書き込まれています。ルックを変えるには、Pixorで変えてpxr shaderをもう一度実行します。
--view-scaleは、アートの1ピクセルが画面の何ピクセルになるかを決めます(既定は4)。ほかのピクセルアートと同じく、整数にしてください。理由はスプライトサイズのガイドに書いてあります。
リアルタイムで省かれるもの
リアルタイムでは、ベイクしたフレームと同じようにフレームを描きますが、3つの違いがあります。
- 投影影なし。面にはライトと帯が付きますが、あるオブジェクトが別のオブジェクトに影を落とすことはありません。
- 奥行きの差がないパーツの線なし。腕の袖のように接しているパーツには、一方が他方の手前にある場所にしか線が付きません。
- フレーム全体を使うステップなし。クリーンアップや、そう印が付いた手描き風のアトムのように、フレーム全体を読んだりフレーム同士を比べたりするステップは、ベイク時にしか動きません。
スタイルの各ノードには、リアルタイムで動くかどうかが書かれています。pxr nodes --graph styleは、各ノードの下に「in real time: yes」か「not yet」を表示します。リアルタイムで動かないノードがグラフにあるスタイルは拒否され、エラーにそのノード名が出ます。--partialを付けると、そのノードを除いた設定のシェーダーを書き出します。
両方使う
いちばん強力なのは、両方を使う構成です。手直し、多数のフレーム、正確なシルエットが必要なキャラクターはシートにベイクします(Godot向けPixorでSpriteFramesとすぐ使えるシーンを紹介しています)。世界、乗り物、ベイクするには大きすぎる、または自由すぎるものは、pxr shaderで描きます。どちらも1つのスタイルから生まれるので、ランプ、帯、パレットを共有し、プレイヤーには2つではなく1つのゲームに見えます。
2Dシーンでライトに反応させたいスプライトには、ライトキット(--export light-kit)が、Godot、Unity、GameMakerでベイクしたスプライトをノーマルマップから照らし、光が当たったピクセルも自分のランプ上にとどまります。パレットに忠実なライティングを参照してください。リアルタイムシェーダーのすべてのオプションは、マニュアルの該当セクションにあります。
よくある質問
リアルタイムシェーダーのUnity版やUnreal版はありますか?
まだありません。pxr shaderが書き出すのはGodot 4のシェーダーだけです。UnityとGameMakerでは、Pixorのライトキットが、それぞれ専用のシェーダーで、ベイクしたスプライトにパレット自身の段でエンジン内のライトを当てます。
リアルタイムのルックはベイクしたスプライトと完全に一致しますか?
同じランプ、明暗の帯、ハイライト、パレットを使います。省かれるのは、投影影、奥行きの差がなく接しているパーツ間の線、そしてクリーンアップのようにフレーム全体を読んだりフレーム同士を比べたりするステップです。
シェーダーのパラメーターを手で設定する必要がありますか?
いいえ。ルックはシェーダーファイルに焼き込まれ、ビューのシーンにカメラと線のパスが入っていて、PixorLook.applyがノード以下のすべてのメッシュに、各メッシュの色とテクスチャを保ったままマテリアルを与えます。