カスタムポストプロセッシング¶
はじめに¶
Godotは、ブルーム、DOF、SSAOを含む多くのポストプロセッシング効果をすぐに利用できます。でも時々、独自のカスタム効果を作成したい場合もあります。そのための方法は次のとおりです。
ポストプロセッシング効果は、Godotがフレームをレンダリングした後に適用されるシェーダーです。最初にシーンを Viewport にレンダリングし、次に ViewportTexture 内で Viewport
をレンダリングして、画面に表示します。
カスタムのポストプロセッシングシェーダーを実装する最も簡単な方法は、Godotの組み込み機能を使用して画面テクスチャから読み取ることです。これに慣れていない場合は、最初に Screen Reading Shaders Tutorial を読む必要があります。
注釈
執筆時点では、Godotは複数のバッファーへの同時レンダリングをサポートしていません。ポストプロセッシングシェーダーは、法線または他のレンダーパスにアクセスできません。レンダリングされたフレームにのみアクセスできます。
シングルパスポストプロセッシング¶
シーンをレンダリングするための Viewport
と、画面上で Viewport
をレンダリングするためのシーンが必要になります。ViewportContainer を使用して、画面全体または別の Control ノード内に Viewport
を表示できます。
注釈
Viewport
を使用してレンダリングすると、フレームレートを含むシーンのレンダリング方法を制御できます。また、ViewportContainer
を使用して2Dシーンに3Dオブジェクトをレンダリングできます。
このデモでは、Node2D を ViewportContainer
とともに使用し、最後に Viewport
を使用します。 [シーン]タブは次のようになります:

``Viewport``の中には、望みのものを保持できます。これにはメインシーンが含まれます。このチュートリアルでは、ランダムボックスのフィールドを使用します:

新しい ShaderMaterial を ViewportContainer
に追加し、新しいシェーダーリソースを割り当てます。レンダリングされた Viewport
には、組み込みの TEXTURE
ユニフォーム(uniform)を使用してアクセスできます。
注釈
ViewportContainer
を使用しないこともできますが、使用する場合は、シェーダーで独自のユニフォーム(uniform)を作成し、次のように Viewport
テクスチャを手動で渡す必要があります:
// Inside the Shader.
uniform sampler2D ViewportTexture;
そして、次のように、GDScriptからシェーダーにテクスチャを渡すことができます:
# In GDScript.
func _ready():
$Sprite.material.set_shader_param("ViewportTexture", $Viewport.get_texture())
次のコードをシェーダーにコピーします。このコードは、シングルパスエッジ検出フィルター、Sobel filter です。
shader_type canvas_item;
void fragment() {
vec3 col = -8.0 * texture(TEXTURE, UV).xyz;
col += texture(TEXTURE, UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz;
col += texture(TEXTURE, UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz;
col += texture(TEXTURE, UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz;
col += texture(TEXTURE, UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz;
col += texture(TEXTURE, UV + SCREEN_PIXEL_SIZE.xy).xyz;
col += texture(TEXTURE, UV - SCREEN_PIXEL_SIZE.xy).xyz;
col += texture(TEXTURE, UV + vec2(-SCREEN_PIXEL_SIZE.x, SCREEN_PIXEL_SIZE.y)).xyz;
col += texture(TEXTURE, UV + vec2(SCREEN_PIXEL_SIZE.x, -SCREEN_PIXEL_SIZE.y)).xyz;
COLOR.xyz = col;
}
注釈
Sobelフィルターは、現在のピクセルの周囲の9x9グリッドのピクセルを読み取り、重みを使用してそれらを加算します。興味深いのは、各ピクセルに重みを割り当てることです。中心の周りの8個のそれぞれに+1、中心のピクセルに-8。重みの選択は「カーネル」と呼ばれます。異なるカーネルを使用して、エッジ検出フィルター、アウトライン、およびあらゆる種類の効果を作成できます。

マルチパスポストプロセッシング¶
ぼかしなどの後処理の効果の中には、リソースを大量に消費するものがあります。ただし、複数のパスでそれらを分解する場合、それらをはるかに高速に実行できます。マルチパスマテリアルでは、各パスは前のパスの結果を入力として処理します。
マルチパスポストプロセッシングシェーダーを作成するには、Viewport
ノードをスタックします。上記の例では、ViewportContainer
ノードを介して、1つの Viewport
オブジェクトのコンテンツをルート Viewport
にレンダリングしました。マルチパスシェーダーに対して同じことを行うには、ある Viewport
のコンテンツを別の Viewport
にレンダリングし、最後の Viewport
をルート Viewport
にレンダリングします。
シーンの階層は次のようになります:

Godotは下の Viewport
ノードを最初にレンダリングします。したがって、シェーダーにとってパスの順序が重要な場合は、最初に適用するシェーダーをツリー内の最も低い ViewportContainer
に割り当てるようにしてください。
注釈
このようにネストせずに、ビューポートを個別にレンダリングすることもできます。 2つのビューポートを使用し、それらを次々にレンダリングするだけです。
ノード構造を除き、手順はシングルパスポストプロセッシングシェーダーと同じです。
例として、次のコードを各 ViewportContainers にアタッチすることにより、フルスクリーンのガウスぼかし効果を作成できます。シェーダーを適用する順序は重要ではありません:
shader_type canvas_item;
// Blurs the screen in the X-direction.
void fragment() {
vec3 col = texture(TEXTURE, UV).xyz * 0.16;
col += texture(TEXTURE, UV + vec2(SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
col += texture(TEXTURE, UV + vec2(-SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.15;
col += texture(TEXTURE, UV + vec2(2.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
col += texture(TEXTURE, UV + vec2(2.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.12;
col += texture(TEXTURE, UV + vec2(3.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
col += texture(TEXTURE, UV + vec2(3.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.09;
col += texture(TEXTURE, UV + vec2(4.0 * SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
col += texture(TEXTURE, UV + vec2(4.0 * -SCREEN_PIXEL_SIZE.x, 0.0)).xyz * 0.05;
COLOR.xyz = col;
}
shader_type canvas_item;
// Blurs the screen in the Y-direction.
void fragment() {
vec3 col = texture(TEXTURE, UV).xyz * 0.16;
col += texture(TEXTURE, UV + vec2(0.0, SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
col += texture(TEXTURE, UV + vec2(0.0, -SCREEN_PIXEL_SIZE.y)).xyz * 0.15;
col += texture(TEXTURE, UV + vec2(0.0, 2.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
col += texture(TEXTURE, UV + vec2(0.0, 2.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.12;
col += texture(TEXTURE, UV + vec2(0.0, 3.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
col += texture(TEXTURE, UV + vec2(0.0, 3.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.09;
col += texture(TEXTURE, UV + vec2(0.0, 4.0 * SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
col += texture(TEXTURE, UV + vec2(0.0, 4.0 * -SCREEN_PIXEL_SIZE.y)).xyz * 0.05;
COLOR.xyz = col;
}
上記のコードを使用すると、次のような全画面ぼかし効果が得られます。

Viewport
ノードの機能の詳細については、Viewports Tutorial を参照してください。