【Godot4.x】Vignetteシェーダーのサンプル

今回はVignetteシェーダーサンプルを紹介します。

シェーダーコードだけ必要な場合は、目次の「Vignetteシェーダーの記述」をクリックすると該当の部分に移動します。

Vignetteシェーダーのサンプル

Vignetteとは

Vignette (ヴィネット) とは、画面の周りを暗くすることで、レトロな印象を与えたり、中心に視線を注目させたり、視界が狭くなることで不安な印象を与える画面効果です。

右側がVignette効果を適用した画像です。少し画面が引き締まった印象がありますね。

この効果の画像素材を作るには Photoshopの「レンズ補正」などのフィルタで作ることになります。

ただゲームでこの効果を使う場合には、暗い部分の範囲を動的に狭くしたり広げたり、または色を変化させたりと、画像データで持つよりもシェーダーで動的に作った方が色々と柔軟に見せることができます。

プロジェクトの作成

プロジェクトを作成します。プロジェクト名は「TestVignette」としました。

ColorRectノードを作成する

シェーダーを適用するためのノードとして「ColorRect」ノードを作成します。

ColorRect」ノードを選びます。

作成したノード名は「VignetteFilter」に変更しました。

Ctrl+S (macOSではCmd+S) でシーンを保存します。

ファイル名は「VignetteFilter.tscn」としておきます。

画面サイズに合わせる

ColorRectのサイズを画面サイズに合わせます。

インスペクタから “Layout > Transform” の “Size” を (1152, 648) に修正すると、Godot4 の初期画面サイズにピッタリ合います。

シェーダーの作成

CanvasItem > Material からドロップダウンをクリックして、「新規 ShaderMaterial」を選びます。

作成した ShaderMaterial をクリックすると、”Shader” の項目が表示されるので <空> をクリックして “新しいシェーダー” を選びます。

そのまま「作成」ボタンを押します。

作成したシェーダーファイルをクリックすると Shader Editor が表示されます。

ここにシェーダーコードを記述していきます。

Vignetteシェーダーの記述

シェーダーは以下のように記述します。

// =============================================================
// Vignette Shader (for Godot4)
// @note 通常は ColorRectノードで実装するのがおすすめ.
// @ref https://godotshaders.com/shader/color-vignetting/
// =============================================================
shader_type canvas_item;

// Vignetteのかかり具合.
uniform float vignette_intensity : hint_range(0.0, 10.0) = 0.4;
// Vignetteの透過値.
uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5;
// Vignetteの色.
uniform vec4 vignette_rgb : source_color = vec4(0.0, 0.0, 0.0, 1.0);
// Vineetteの境界のぼやけ具合 (通常は "vignette_intensity" で調整するけれど念のため作成).
uniform float vinnette_size : hint_range(0.0, 100.0) = 15.0;
// hint_screen_texture で Viewportテクスチャを取得する.
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;

// Vignetteの計算.
float vignette(vec2 uv) {
	uv *= 1.0 - uv.xy;
	// 円のグラデーションを作る.
	float vignette = uv.x * uv.y * vinnette_size;
	return pow(vignette, vignette_intensity * vignette_opacity);
}

// フラグメントシェーダーの記述.
void fragment(){
	// "SCREEN_UV" で解像度を考慮した色を取得.
	vec4 color = texture(screen_texture, SCREEN_UV);
	vec4 text = texture(TEXTURE, UV);
	
	text.rgba *= (vignette_rgb.rgba);
	text.rgba *= (1.0 - vignette(UV));
	
	COLOR = vec4((text.rgb)*color.rgb,text.a);
}

このコードは GodotShader の「Color vignette」からお借りしました。

Godot4 になって「SCREEN_TEXTURE」キーワードがなくなったようなので、その部分だけ置き換えています。

シェーダーパラメータはいくつか定義されていますが、基本的には「vignette_intensity」「vignette_opacity」「vignette_rgb」の3つで調整します。

  • vignette_intensity: Vignetteの暗い部分の密集度
  • vignette_opacity: Vignetteの不透明度 (0.0〜1.0)
  • vignette_rgb: Vignetteの色

パラメータの変化は “Shader Parameters” から確認できます。

GDScriptから値を変更する

スクリプトからパラメータを変更するには以下のように記述します。

別のシーンからこのシーンを instantiate() してから直接 material.get_shader_parameter() で変更することができますが、今回はサンプルということで “VignetteFilter” シーンに直接スクリプトをアタッチします。

そのまま「作成」をクリックします。

スクリプトは以下のように記述します。

extends ColorRect

var _timer = 0.0

func _process(delta: float) -> void:
	_timer += delta
	
	var alpha = abs(sin(_timer * 2)) # sinカーブで変化させる.
	_set_vignette(alpha)

## Vignetteの透過値を設定する.
func _set_vignette(alpha:float, intensity:float=0.4) -> void:
	var mat:ShaderMaterial = material
	mat.set_shader_parameter("vignette_opacity", alpha)
	mat.set_shader_parameter("vignette_intensity", intensity)

sinカーブで “viginette_opacity” の値を変化させるようにしてみました。

では実行して動作を確認します。

今回はこのシーンをメインシーンとして実行します。

すると一定間隔で明滅する Vignette となります。

実際にゲームで使用する場合には “vignette_rgb” を赤色にして、ダメージ演出とするのがよくある使われ方ですね。

完成プロジェクト

今回作成したプロジェクトファイルを添付しておきます。