本日はShader学習枠です。
〇メッシュの向き
前回シェーダーの最適化にかかわる処理であるカリングを紹介しました。
カリングは面の向きに応じて描画しない面を設定するという機能でした。
これによって描画の無駄を省き処理を軽くすることができます。
今回は関連して面の向きを取得して面の向きによって処理を手動で分けていきます。
今回はメッシュの向きに応じて色を変える処理を行うためカリングをOffにします。
SubShader { Tags { ・・・ } LOD 100 Cull Off
カリングはデフォルトでオンになっており上記の定義を行わない限り裏面がカリングされ面の表面のみが描画されるようになっています。
メッシュの向きの情報を取得するためにはフラグメントシェーダーの引数にbool型の変数を追加します。
ここではfacingという変数名で定義して、セマンティクスとしてSV_IsFrontFaceを定義しています。
float4 frag(v2f i, bool facing : SV_IsFrontFace) { }
SV_IsFrontFaceによってメッシュの向きを取得できます。 True(1)が正面でFalse(0)が裏面を返します。
なお古いシェーダーでVFACEが使用されているものも見かけますが、これはDirectX10以前で使用されていた形になります。
Semantics - Win32 apps | Microsoft Learn
後はfacingの値に応じて条件分岐を行います。
col *=(facing ? 1.0 : 0);
今回は表面には1を、裏面には0を掛け合わせて裏面の出力値が黒(float4(0,0,0,0))になるように指定しました。
float4 frag(v2f i, bool facing : SV_IsFrontFace) : SV_Target { // sample the texture float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); col *=(facing ? 1.0 : 0); return col; }
これを実行すると次のような結果が得ることができます。
条件演算子の1,0の値を任意の値に変換することで任意の処理にカスタマイズすることができます。
col *=(facing ? 1.0 : 0);
本日は以上です。
〇コード全文
Shader "Unlit/NewUnlitShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _NormalMap("NormalMap",2D) = "bump" {} } SubShader { Tags { "RenderType"="Opaque" }//Shader属性 LOD 100 Cull Off Pass//Shaderのパス { HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap); v2f vert(appdata v) { v2f o; o.vertex = TransformObjectToHClip(v.vertex); o.uv = v.uv; return o; } float4 frag(v2f i, bool facing : SV_IsFrontFace) : SV_Target { // sample the texture float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv); col *=(facing ? 1.0 : 0); return col; } ENDHLSL } } }