シェーダー勉強内容(2022年7月)
はじめに
2022年7月に勉強した内容です。
過去の記事はこちら
Unity
今回も2DのURP対応シェーダーを開発していました。
ステンシルによる鏡
ステンシルを使って2Dゲームで鏡に物を映らせることができるようになりました。
ただ、現在の方法だと鏡の前にはプレイヤーしか映すことができず、ほかのオブジェクトを映らせることができません。
ここら辺は正直にC#を使うべきかもしれません。
テクスチャのパラメータのデフォルト値
現在のSkadiShaderにはテクスチャ1枚で
Outline
Emission
Stencil(現状は使えない)
の設定をすることができますが、パパっと挙動を確かめたいときなどにこれらのテクスチャの設定がしっかりとされていないと動かないという問題が多かったのでそれぞれの機能に0か1をぱっと割り当てれるようにしました。
これによってキャラクターの元の色を確認したいときなどにGUIからデフォルトの値を使うというのにチェックを入れればすぐにOffにすることができます。
struct v2f
{
//==================//
// x : outline //
// y : emission //
// z : stencil //
// w : not used //
//==================//
float4 OESDefault : TEXCOORD3;
};
一つTEXCOORDを用意し、
v2f vert (appdata v)
{
// OESDefault
if(_UseOutlineDefault) o.OESDefault.x = _OutlineDefault;
if(_UseEmissionDefault) o.OESDefault.y = _EmissionDefault;
if(_UseStencilDefault) o.OESDefault.z = 0;
o.OESDefault.w = 0;
}
頂点シェーダーの時点でデフォルト値を使う要素があるのならばデフォルト値を入れます。
デフォルト値はGUIで0(Black)か1(White)を入れれるようになってます。
float4 frag (v2f i) : SV_Target
{
// outlineCol
float3 outlineCol = (outline.xxx * _OutlineColor) * _UseOutline;
float outlineAlpha = (outline * _OutlineColor.a) * _UseOutline;
// 強制デフォルト値を使うのならば
if(_UseOutlineDefault)
{
outlineCol = i.OESDefault.x;
outlineAlpha = i.OESDefault.x;
}
}
その値をピクセルシェーダーで使います。
if文を使って分岐するよりもバリアントで分岐しようと思ったことがありますがこの機能自体は値を一時的に変えるだけなのでバリアントでシェーダーの種類を増やすようなものでは無いと思ったのでif文を使うことにしました。
3Passができなかった
URPでPassを増やして3Passにすることができませんでした。
やる方法があるのかもしれませんがわかりませんでした。
今までのSkadiShaderは
BasePass キャラクターのメインとなる色を描画
OutlinePass アウトラインだけをこれで描画
という2Pass構成をしており、ここにステンシルのPassを加えようとしたら3Passになり、3Pass目が呼ばれませんでした。
//1Pass目
Pass
{
Name "firstPass"
Tags
{
"LightMode" = "Universal2D"
}
}
//2Pass目
Pass
{
Name "secondPass"
Tags
{
"LightMode" = "SRPDefaultUnlit"
}
}
2DのURPではこのようにLightModeを指定してPassを作っていくのですが、
SRPDefaultUnlitを2つ、3つ…というようにドンドン増やしたら3Pass目も作れるのではないのかと思っていましたが無理でした。SRPDefaultUnlitは1つだけじゃないといけないのかもしれません…
なので一番新しいSkadiShaderではBaseとOutlineで2Pass構成になっていたのを1Passに統合しました。
今後
現状Sprite用のシェーダーはもうほぼ完成しているかなって感じなので今後は制作中のゲームに合わせたUIやエフェクト用のシェーダーを開発していくと思います。