シェーダーの紹介
このページではシェーダーとは何かについて説明し、Godotでシェーダーがどのように機能するかの概要を示します。エンジンのシェーディング言語の詳細なリファレンスについては、doc_shading_lang を参照してください。
シェーダーはグラフィックスプロセッシングユニット (GPU) 上で実行される特別な種類のプログラムです。当初は3Dシーンのシェーディングに使用されていましたが、現在ではさらに多くのことができるようになりました。これらを使用してエンジンが画面上にジオメトリとピクセルを描画する方法を制御し、あらゆる種類の効果を実現できます。
Godotのような最新のレンダリング エンジンは、すべてをシェーダーで描画します。グラフィックスカードは何千もの命令を並行して実行できるため、驚異的なレンダリング速度が実現します。
ただしシェーダーは並列的な性質があるため、一般的なプログラムのように情報を処理しません。シェーダーコードは各頂点または各ピクセル上で個別に実行されます。フレーム間にデータを保存することもできません。そのためシェーダーを使用する場合は、他のプログラミング言語とは異なるコーディングと考え方が必要になります。
例えばテクスチャ内のすべてのピクセルを特定の色にセットするとします。 GDScriptのコードでは for ループを使用します:
for x in range(width):
for y in range(height):
set_color(x, y, some_color)
シェーダーではコードはすでにループの一部であるため、実際に書くコードは次のようになります。
void fragment() {
COLOR = some_color;
}
注釈
グラフィックスカードは描画するピクセルごとに fragment() 関数を1回以上呼び出します。詳細については以下をご覧ください。
Godotのシェーダー
Godotは一般的なOpenGL Shading Language (GLSL)に基づいて簡略化されたシェーディング言語を提供します。このエンジンは低レイヤーの初期化作業の一部を代替してくれるため、ユーザーは複雑なシェーダーの作成が容易になります。
Godotではシェーダーは「プロセッサー関数」と呼ばれる主要な関数で構成されています。プロセッサー関数はシェーダープログラムへのエントリーポイントです。Godotシェーダーには7つの異なるプロセッサー関数があります。
vertex()関数はメッシュ内のすべての頂点に対して実行され、頂点の位置と他の変数を設定します。 CanvasItemシェーダー および Spatial(空間)シェーダー で使用されます。fragment()関数はメッシュで覆われているすべてのピクセルに対して実行されます。これはvertex()関数によって出力した値が頂点間で補間された値を使用します。 CanvasItemシェーダー および Spatial(空間)シェーダー で使用されます。light()関数はすべてのピクセルおよびすべてのライトに対して実行されます。これはfragment()関数とその以前の実行から変数を受け取ります。 CanvasItemシェーダー および Spatial(空間)シェーダー で使用されます。start()関数はパーティクルが最初に生成されるときに、パーティクル システム内のすべてのパーティクルに対して1回実行されます。 パーティクルシェーダー で使用されます。process()関数はフレームごとにパーティクルシステム内のすべてのパーティクルに対して実行されます。 パーティクルシェーダー で使用されます。sky()関数は、放射キューブマップを更新する必要がある場合、放射キューブマップ内のすべてのピクセルに対して実行され、また現在の画面上のすべてのピクセルに対して実行されます。 スカイシェーダー で使用されます。fog()関数は、フォグボリューム と交差するボリューメトリックフォグのフロクセルバッファ内のすべてのフロクセルに対して実行されます。 フォグシェーダー によって使用されます。
警告
vertex_lighting レンダー モードが有効になっている場合、またはプロジェクト設定で [レンダリング] > [品質] > [シェーディング] > [頂点シェーディングの強制] が有効になっている場合、 light() 関数は実行されません。モバイル プラットフォームではデフォルトで有効になっています。
注釈
Godot はユーザーが完全にカスタムの GLSL シェーダを作成できるAPIも公開しています。詳細については、コンピュートシェーダー を参照してください。
シェーダーの種類
すべての用途 (2D、3D、パーティクル、スカイ、フォグ) に汎用的な設定を提供する代わりに、Godotシェーダーは目的を指定する必要があります。タイプが異なれば、サポートされるレンダリング モード、ビルトイン変数、プロセッサー関数も異なります。
Godotではすべてのシェーダーは、最初の行で次の形式でタイプを指定する必要があります:
shader_type spatial;
利用可能なタイプは次のとおりです。
spatial: 3Dレンダリング用。
canvas_item: 2Dレンダリング用。
particles: パーティクルシステム用。
fog: FogVolumes(ボリューメトリック フォグ) の描画用
レンダリングモード
シェーダーにはレンダリングモードのオプションがあり、次のようにシェーダータイプの後の2行目以降で指定できます。
shader_type spatial;
render_mode unshaded, cull_disabled;
レンダリングモードはGodotがシェーダーを適用する方法を変更します。たとえば unshaded モードでは、エンジンは内蔵のライトプロセッサー機能をスキップします。
各シェーダータイプには異なるレンダリング モードがあります。レンダリングモードの完全なリストについては、各シェーダータイプのリファレンスを参照してください。
頂点プロセッサー
vertex() 処理関数は spatial および canvas_item シェーダーのすべての頂点ごとに1回呼び出されます。
ワールドのジオメトリの各頂点には、位置や色などのプロパティがあります。このプロセッサー関数はこれらの値を変更し、フラグメントプロセッサーに渡します。またこれを使用して追加のデータをvaringsに渡すことでフラグメントプロセッサーに送信することもできます。
デフォルトではGodotはジオメトリを画面に投影するために必要な頂点データを変換します。またレンダリングモードを指定することで頂点データを自分で変換することも可能です。具体例については、Spatial(空間)シェーダー を参照してください。
フラグメントプロセッサー
fragment() 処理関数はピクセルごとにGodotマテリアルのパラメータを設定するために使用されます。このコードはオブジェクトまたはプリミティブが描画するすべての可視ピクセル上で実行されます。これは spatial 、 canvas_item 、および sky シェーダーでのみ使用できます。
フラグメント関数の標準的な使用法は、ライティングの計算に使用されるマテリアルプロパティを設定することです。たとえば、ROUGHNESS、RIMまたは TRANSMISSION の値を設定して、ライトがそのフラグメントにどのように応答するかをライト機能に伝えます。これにより、ユーザーが多くのコードを記述することなく、複雑なシェーディングパイプラインを制御できます。この組み込み機能が必要ない場合は、それを無視して独自のライト処理関数を記述すれば、Godotはそれを最適化します。たとえば、RIM に値を書き込まない場合、Godotはリム照明を計算しません。コンパイル中、Godotは RIM が使用されているかどうかを確認します。そうでない場合は、対応するすべてのコードを切り取ります。したがって、使用しない効果の計算を無駄にすることはありません。
ライトプロセッサー
light() プロセッサーもピクセルごとに実行され、オブジェクトに影響を与えるすべてのライトごとに1回実行されます。オブジェクトに影響を与えるライトがない場合は実行されません。これは fragment() プロセッサー内で呼び出される関数として存在し、通常は fragment() 関数内で設定されたマテリアルプロパティで動作します。
light() プロセッサは2Dと3Dでは動作が異なります。それぞれの機能の説明については、各ドキュメント CanvasItem シェーダ および Spatial(空間)シェーダ を参照してください。