夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

ゼロから始めるUnityShader開発 第四章 面の取得

本日はShader学習枠です。

〇メッシュの向き

前回シェーダーの最適化にかかわる処理であるカリングを紹介しました。

redhologerbera.hatenablog.com

カリングは面の向きに応じて描画しない面を設定するという機能でした。

これによって描画の無駄を省き処理を軽くすることができます。

 今回は関連して面の向きを取得して面の向きによって処理を手動で分けていきます。

 今回はメッシュの向きに応じて色を変える処理を行うためカリングを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
        }
    }
}