【Godot】トランジション(画面切り替え)をシェーダで作る

はじめに

ゲームの画面切り替えの際、フェードインやフェードアウトすることがあります。

こうした画面切り替えの演出をトランジションエフェクトといいます。

今回はちょっと凝った切り替えもやってみようと思います。

例えばこんなトランジション。ノベルゲームとかでよく見ますね。

f:id:ueshita:20200917122208g:plain

背景イラストは きまぐれアフター さんからお借りしました。

トランジションエフェクトを実装する

ルール画像

トランジションにはルール画像というモノクロ画像を使います。

今回は For You さんからお借りしました。

f:id:ueshita:20200917114701p:plain

シェーダを記述する

今回はVisualShaderを使いました。ノードベースなシェーダは楽でいいですね。

このシェーダはルール画像をマスクとして使い、黒いところから徐々に透けていくようにsmoothstep関数を使って記述しました。

f:id:ueshita:20200917120150p:plain

一応シェーダコード版も載せておきます。

shader_type canvas_item;

uniform float SoftRange = 0.02;   // 境目を半透明にする幅
uniform float Value = 0.0;        // フェード値
uniform sampler2D Mask;

void fragment()
{
    float rangedValue = Value * (SoftRange * 2.0 + 1.0) - SoftRange;
    float maskValue = texture(Mask, UV).r;
    float minValue = rangedValue - SoftRange;
    float maxValue = rangedValue + SoftRange;
    float alpha = smoothstep(minValue, maxValue, maskValue);
    COLOR = vec4(vec3(0.0), alpha);
}

マテリアルを設定する

背景絵を表示するBGPanelと、トランジション演出を表示するTransitionPanelを設定します。

TransitionPanelにはShaderMaterialを設定し、先ほど作成したシェーダを設定します。

f:id:ueshita:20200917153926p:plain

Shader ParamValueをマウスでドラッグすると、どんな感じになるかプレビューできます。

スクリプトを書く

extends Panel

onready var shader_mat := material as ShaderMaterial

const duration = 1.0   # トランジション時間
var shader_value := 0.0    # シェーダに渡す値
var is_fading := false  # 処理のスイッチ

func _process(delta: float):
    # Spaceキーを押したら開始
    if Input.is_action_just_pressed("ui_accept"):
        is_fading = true
        shader_value = 0.0
    
    # ESCキーを押したらリセット
    if Input.is_action_just_pressed("ui_cancel"):
        is_fading = false
        shader_value = 0.0
    # トランジション(フェード)処理
    if is_fading:
        shader_value = min(1.0, shader_value + delta / duration)
    # シェーダマテリアルに値をセット
    shader_mat.set_shader_param("Value", shader_value)

実行結果

f:id:ueshita:20200917204023g:plain

ほかの例

色々なルール画像を使って面白いトランジションエフェクトができます。

f:id:ueshita:20200917205359g:plain

補足

今回は黒一色に暗転するエフェクトのみの解説でしたが、他の画像やレンダリングしたビューポートをテクスチャとして使うと、クロスフェード的な画面切り替えもできると思います。