前回は、Unity で新規作成した Unlit シェーダープログラムを変更して、 Inspector ウィンドウからシェーダーで作成するタイルマップの影の色を指定する手順を紹介しました。
前回の記事:Unity Unlitシェーダーを変更し、マップチップの影を描画する | Compota-Soft-Press
しかし、指定した色をピクセルシェーダーで用いても、Scene 内の影用タイルマップの色には反映されず、指定した灰色ではなく黒色が表示されました。
今回は、Inspector ウィンドウで指定した色をシェーダーの処理結果に反映させるための原因と対策について紹介します。
具体的には、Unity のシェーダープログラムで、 Properties に追加した Color 型のシェーダープロパティを、実際に色を決定する処理を行う frag 関数(フラグメントシェーダー≒ピクセルシェーダー)で参照できるようにするためのマッピングの手順を説明します。
※ Unity は 2021.3.14f1、Test Framework パッケージは Version 1.1.33、Visual Studio は Community 版 Version 17.2.5、 OS は Windows 10 です。
シェーダープロパティの Cg 言語からのマッピング
以前に紹介したように、シェーダーのプログラムは、 ShaderLab 言語と Cg (≒HLSL) 言語の部分で構成されます。
以前の記事:Unity Unlitシェーダーの初期プログラムのキーワードと構造 | Compota-Soft-Press
ShaderLab 言語の Properties ブロックで定義したシェーダープロパティは、 Unity エディタの Inspector の Shader の設定部分に表示されます。
このシェーダープロパティを、 Cg 言語の部分で参照するには、Properties で指定した名前で、Cg 言語に対応した型で定義します。
前回、 _MainTex という Texture シェーダープロパティを参考にして、 Color シェーダープロパティを次のように Cg 言語の部分で定義しました。
sampler2D _ShadowColor;
float4 _ShadowColor_ST;
しかし、この _ShadowColor_ST を使って、 frag 関数で影の色を返したのに、設定した灰色ではなく真っ黒な色で四角く塗りつぶされてしまいました。
これは、シェーダープロパティを Cg 言語から参照する際は、シェーダープロパティの Texture や Color といった型に応じて、 Cg 言語で同じ名前で定義するときの型が異なるからです。
例えば次のシェーダープロパティ
_MyColor ("Some Color", Color) = (1,1,1,1) _MyVector ("Some Vector", Vector) = (0,0,0,0) _MyFloat ("My float", Float) = 0.5 _MyTexture ("Texture", 2D) = "white" {} _MyCubemap ("Cubemap", CUBE) = "" {}
について、Cg/HLSL で参照するために宣言するコードは以下のとおりです。
fixed4 _MyColor; //color には通常、低精度型で十分です float4 _MyVector; float _MyFloat; sampler2D _MyTexture; samplerCUBE _MyCubemap;
Cg/HLSL は uniform キーワードを記述できますが、必須ではありません。
uniform float4 _MyColor;
ShaderLab のプロパティタイプは Cg/HLSL 変数タイプとの対応は次のようにマッピングされます。
Cg/HLSL でシェーダープロパティを参照する – Unity マニュアル https://docs.unity3d.com/ja/2019.4/Manual/SL-PropertiesInPrograms.html
- Color と Vector のプロパティは float4, half4 または fixed4 変数にマップされています。
- Range と Float プロパティは float, half または fixed 変数にマップされています。
- Texture プロパティは、通常( 2D )のテクスチャの場合はsampler2D変数に、キューブマップの場合は samplerCUBE に、3D テクスチャの場合はsampler3D変数にマップされています。
上記の引用によると、 Color は fixed4 という型で同じ名前で定義すると Cg 言語にマッピングされピクセルシェーダーなどの処理で参照できるようになります。
引用に書かれているシェーダープロパティの型と、 Cg 言語にマッピングする際の型の対応関係をまとめます。
シェーダープロパティの型 | Cg 言語でマッピングする際の型 |
Color | fixed4 |
Vector | float4 |
Float | float |
2D | sampler2D |
CUBE | samplerCUBE |
そこで、以下のようにコードを変更しました。
// シェーダープロパティの定義
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_ShadowColor("Shadow color", Color) = (.1, .1, .1, 1) // 影用カラーを追加
}
// ここからは Cg 言語での処理の一部
// テンプレートの _MainTex シェーダープロパティを Cg 言語で参照するための定義
sampler2D _MainTex;
float4 _MainTex_ST;
// 追加した Color シェーダープロパティを Cg 言語で参照するための定義
fixed4 _ShadowColor;
// ピクセルシェーダーの処理。指定座標に設定する色を返す。
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// 追加した _ShadowColor の色を返す。アルファ値は _MainTex から取得している。
fixed4 shadowCol = fixed4(_ShadowColor.x, _ShadowColor.y, _ShadowColor.z, col.w);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, shadowCol);
return shadowCol;
}
前回は _MainTex シェーダープロパティの真似をして、 sampler2d や float4 で _ShadowColor を Cg 言語で定義しました。
しかし、 Color は Texture と異なり Fixed4 型にするようなので、そのように変更し、 frag 関数でも _ShadowColor_ST ではなく _ShadowColor から r, g, b に対応する x, y, z を得ました。
※ちなみに Fixed4 型の 4 番目の要素は w です。
この結果、シェーダーを適用した画像は真っ黒ではなく、 _ShaderColor シェーダープロパティで設定した灰色で表示されるように改善しました。
しかし、まだ、スプライト画像からのアルファ値は反映されていないため、シェーダーを適用している描画範囲全体が四角く灰色で塗りつぶされています。
今回はここまで
今回は Unity の Unlit Shader のテンプレートに Color 型のシェーダープロパティを追加し、それを Cg(≒HLSL) 言語でマッピングして利用するための変数の定義を紹介しました。
それにより、ピクセルシェーダーの処理で返す色を、 Unity エディタで設定した Color 型のシェーダープロパティの色と同じにすることができました。
次回は、シェーダーを適用しているタイルマップの画像のアルファ値を反映させて指定した色の影に形をつける実装を紹介します。
参照サイト Thank You!
記事一覧 → Compota-Soft-Press
コメント