今回は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” を赤色にして、ダメージ演出とするのがよくある使われ方ですね。
完成プロジェクト
今回作成したプロジェクトファイルを添付しておきます。