この記事では、2D画像をもとに擬似的な影を実装する方法について紹介します。
目次
影の実装
今回の素材は「立ち絵素材 わたおきば」様よりお借りしています。
背景が明るいほうがわかりやすいので、ColorRect
を背面に配置して明るい灰色にします。

登録したキャラクター画像は Chara
にノード名を変更しておきます。

影用のSpriteとして、Chara
を複製し、名前を Shadow
にリネームします。

図ではわかりやすいように位置をずらしていますが、Shadow
ノード の Transform > Position
は 0 (初期値) にしておきます。

そして、Chara
ノードを選択して、インスペクタから Z Index > Z Index
を 「1」にしておきます。

これはキャラクターを影よりも前面に表示したいためとなります。
さらに Shadow
ノードを選択して、インスペクタから Z Index > Z Index
を 「-1」にしておきます。

少しややこしいですが、Z Indexの並びは以下のようになります。
Mainシーン
+-- ColorRect (0) => 一番奥
+-- Chara (1) => 一番手前
+-- Shadow (1-1=0) => 真ん中
Shadow
ノードを選択した状態で、CanvasItem > Material > Material > [空]
をクリックして「新規 Shader Material」を追加します。

作成されたMaterialをクリックして、Shader > [空]
をクリックし、「新規 Shader」を選びます。

するとシェーダーエディタが表示されるので以下のコードを記述します。
shader_type canvas_item;
uniform float shearAngleX = -45.0;
uniform float sunAngle = 45.0;
//const float SHEAR_ORIGIN_Y = 1.0; // 左上が原点
const float SHEAR_ORIGIN_Y = 0.5; // 中心が原点
// 頂点シェーダー
void vertex()
{
vec2 v = VERTEX;
float originOffsetY = SHEAR_ORIGIN_Y / TEXTURE_PIXEL_SIZE.y;
v.y -= originOffsetY; // 原点をずらす
// 影の傾きを計算
v.y *= cos(radians(shearAngleX)) / tan(radians(sunAngle));
v.x += tan(radians(shearAngleX)) * v.y;
v.y += originOffsetY; // 原点をもとに戻す
VERTEX = v;
}
// フラグメントシェーダー
void fragment()
{
// 薄い黒色にする
vec4 color = texture(TEXTURE, UV);
color.rgb = vec3(0, 0, 0);
color.a *= 0.5;
COLOR = color;
}
シェーダーコードを記述すると、以下のように影が描画されます。

Shadow
ノードにスクリプトをアタッチして以下のように記述します。
tool
extends Sprite
export(float, -90, 90) var shear_angle_x = -45
export(float, 45, 90) var sun_angle = 45
func _process(delta: float) -> void:
material.set_shader_param("shearAngleX", shear_angle_x)
material.set_shader_param("sunAngle", sun_angle)
tool宣言をしているので、シーンをいったん保存して開き直します。
するとエディタから影の調整ができるようになります。
