「【Unity 2020.2】物陰に隠れた部分を描画する - rn.log 」はデプスを頼りにシルエットを描画する方式のようですね。このやり方ですとおそらく2Dゲームには不向きでしょうから、「【Unity】2Dゲームでプレイヤーがオブジェクトに回り込んだ時にシルエットを表示する - PG日誌 」の方針で行った方がいいんじゃないかと思います。
ステンシル機能を使った方法を検討してみました。まずPackages/Universal RP/Shaders/2D/Sprite-Lit-Default.shader
を複製して別名(とりあえずSprite-Lit-Default-Stencil.shader
としました)を付け、内容を下記のように変更しました。
ShaderLab
1 // シェーダー名を変更して区別が付くようにする
2 Shader "Universal Render Pipeline/2D/Sprite-Lit-Default (Stencil)"
3 {
4 Properties
5 {
6 _MainTex("Diffuse", 2D) = "white" {}
7 _MaskTex("Mask", 2D) = "white" {}
8 _NormalMap("Normal Map", 2D) = "bump" {}
9
10 // Legacy properties. They're here so that materials using this shader can gracefully fallback to the legacy sprite shader.
11 [HideInInspector] _Color("Tint", Color) = (1,1,1,1)
12 [HideInInspector] _RendererColor("RendererColor", Color) = (1,1,1,1)
13 [HideInInspector] _Flip("Flip", Vector) = (1,1,1,1)
14 [HideInInspector] _AlphaTex("External Alpha", 2D) = "white" {}
15 [HideInInspector] _EnableExternalAlpha("Enable External Alpha", Float) = 0
16
17 // ステンシル用プロパティを追加する
18 _StencilComp ("Stencil Comparison", Float) = 8
19 _Stencil ("Stencil ID", Float) = 0
20 _StencilOp ("Stencil Operation", Float) = 0
21 _StencilWriteMask ("Stencil Write Mask", Float) = 255
22 _StencilReadMask ("Stencil Read Mask", Float) = 255
23 }
24
25 SubShader
26 {
27 Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" }
28
29 Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
30 Cull Off
31 ZWrite Off
32
33 // Stencilブロックを追加する
34 Stencil
35 {
36 Ref [_Stencil]
37 Comp [_StencilComp]
38 Pass [_StencilOp]
39 ReadMask [_StencilReadMask]
40 WriteMask [_StencilWriteMask]
41 }
42
43 // 中略...主要部分は変更なし
44 }
45
46 Fallback "Sprites/Default"
47 }
そして、これを使ったマテリアルを3種類作成しました。
キャラクター用は
Stencil Comparison: 8(常にステンシルテスト通過)
Stencil ID: 2
Stencil Operation: 2(Stencil IDをステンシルバッファに書き込む)
Stencil Write Mask: 3(ステンシルバッファの下2桁にのみ書き込む)
Stencil Read Mask: 255(ステンシルバッファのすべての桁から読み込む...読み込みは行わないのでこの設定は重要ではありません)
として、遮蔽物用は
Stencil Comparison: 8(常にステンシルテスト通過)
Stencil ID: 1
Stencil Operation: 2(Stencil IDをステンシルバッファに書き込む)
Stencil Write Mask: 1(ステンシルバッファの下1桁にのみ書き込む)
Stencil Read Mask: 255(ステンシルバッファのすべての桁から読み込む...読み込みは行わないのでこの設定は重要ではありません)
として、シルエット用は
Stencil Comparison: 3(Stencil IDとステンシルバッファ上の値が一致したらステンシルテスト通過)
Stencil ID: 3
Stencil Operation: 0(ステンシルバッファへの書き込みは行わない)
Stencil Write Mask: 255(ステンシルバッファのすべて桁に書き込む...書き込みは行わないのでこの設定は重要ではありません)
Stencil Read Mask: 3(ステンシルバッファの下2桁のみから読み込む)
としました。
キャラクターにはキャラクター用の、遮蔽物には遮蔽物用のマテリアルをセットし、さらにカメラの子オブジェクトとして画面全体を覆うサイズの四角いスプライトを配置し、シルエット用のマテリアルをセットしました。
このシルエット用オブジェクトはSorting LayerやOrder in Layerを調整して、キャラクターや遮蔽物よりも手前に描画されるようにしておきます。
このようにシーンを構成したところ、下図のようにシルエットが描画されました。キャラクターがステンシルバッファに2を書き込み、もしその上に遮蔽物が描画されるとステンシル値の下1桁が1になることでステンシル値は3となり、最後にステンシル値が3のところにシルエットを塗ればいいだろうと思ったわけです。
ちなみに、遮蔽物の描画後にさらにキャラクターが描画された場合はステンシル値が2に戻りますので、そこにはシルエットは描画されなくなります。
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2022/10/24 04:01