この記事では Godot Engine でマスクを実装する方法について解説します。
マスクとは
マスクとは、画像の特定部分を切り抜いて描画する方法です。

この GIF動画では、円形で画像をくり抜いて、その部分だけを描画するようにしています。
画像の準備
目次
マスク用に使う画像は、くり抜きたい部分を完全な白色 (R,G,B)=(255,255,255)
にして、描画したくない部分は透過値を 0 に近づけます。

透過値のある画像を作るには、GIMPなどのグラフィックツールが必要です。
今回使用する素材一式を用意しました
mask.png: マスクする丸の画像
mask2.png: マスクする丸の画像(ふちがぼやけている)


2Dシーン (ノード名は “Main” ) を作成して、”bg.jpg” と “ch.png” を配置します。

キャラ画像が大きすぎた……ので、気になる場合は小さくしてもいいかもしれません。
マスクをするために Light2D
を作成します。

どこに追加しても良いですが、ひとまず ch ノードの下に追加しておきます。

“mask.png” をプロジェクトに追加して、Light2D
のテクスチャに設定します。

さらに Light2D
の Modeを 「Mix」にします

chノード(Sprite
)を選択して、インスペクタから CanvasItem > Material > Material > [空]
をクリックして、「新規 CanvasItemMaterial」を選択します。

表示された CanvasItemMaterialをクリックして、LightMode > Light Only
を選びます

するとこのようにマスクがかかります。

Main(2Dシーン)のスクリプトをアタッチして以下のように記述します。
extends Node2D
onready var light = $ch/Light2D
func _process(delta: float) -> void:
# ライトの座標をマウスの座標に設定する
light.position = get_viewport().get_mouse_position()
これで実行するとマウスの位置がくり抜かれる……はずなのですが、少しずれることがあります。”ch”ノードにぶら下げてしまったためで、”ch”ノードが原点に配置されていない場合はズレが発生します
なので、Light2D
をMainノード直下に移動させます。

そしてスクリプトを修正します。
extends Node2D
onready var light = $Light2D # Mainノード直下に移動した
func _process(delta: float) -> void:
# ライトの座標をマウスの座標に設定する
light.position = get_viewport().get_mouse_position()
実行するとマウスの中心を基準にくり抜かれるようになりました。

円のフチをぼやけた画像にすると、境界がぼやっとした感じになります。
“mask2.png” をプロジェクトに追加し、Light2D > Texture
に割り当てます。

実行するとフチがぼやけた感じになりました!

複数のマスクを同時に使いたい場合は、CanvasItem > Visibility > Light Mask
の設定をマスクされる画像と Light2D
で合わせると、特定の画像に特定のマスクを割り当てる……ということもできます。

※追記
Modeが Mix
の場合は Light Mask
の設定はうまく行かなさそうです。
複数のマスクを別々に適用したい場合には、以下の動画のように Light2D
の Mode を Mask
に設定して、ViewportTexture
経由でマスクする必要がありそうです(未検証)