夜風のMixedReality

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

Unity Shader内で面の裏と表を取得する

本日はShader学習枠です。

UnityのShaderではSubShader内でCull(Culling)を記述することで3Dモデルのメッシュの表と裏、どちらを描画しないかを記述することができます。

SubShader
 {
   
   Cull Off
   Pass{
        ...
      }
 }

Cull Frontは面の表面をCulling=描画対象から外します。 つまり面の裏面のみが描画されます。

Cull Backは面の裏面をCulling=描画対象から外します。 つまり面の表面のみが描画されます。(一般的なShaderの描画)

また面の表裏どちらも描画したい場合としてCull Offを使用することもできます。

今回は面の表と裏どちらも描画しつつ裏と表で違う見た目を描画します。

〇メッシュの表と裏を取得する。

Shaderではメッシュの向きを取得するセマンティクスが提供されています。

 fixed facing :VFACE;

通常セマンティクスはv2f構造体などに記述しますがこちらはフラグメントシェーダーに直接定義しています。

これはおそらくVertexShaderでは使用しないため(データを受け渡さず必要がなく定義済みの変数である)と考えられます。

 fixed4 frag (v2f i,fixed facing:VFACE) : SV_Target
            {
                fixed4 col =facing >0 ? fixed4(1,1,1,1):fixed4(1,0,0,1); 
                return col;
            }

上記の例の場合facingが正の数の場合表、負の数の場合裏を向いていると取得しています。

今回は面の表面は白、裏面は赤を描画するようにしています。

Unityのプリミティブ円柱にアタッチしてNearClipを使用して表面と裏面が見えるようにカメラを配置するとシェーダーが想定道理に動いていることを確認できます。

f:id:Holomoto-Sumire:20220207211112p:plain

今回のshaderでは面の両面を描画する必要があるためCull Offで使用しています。

〇コード全文

Shader "Unlit/BothRenderingShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Cull Off
        Pass
        {
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i,fixed facing:VFACE) : SV_Target
            {
                fixed4 col =facing >0 ? fixed4(1,1,1,1):fixed4(1,0,0,1); 
                return col;
            }
            ENDCG
        }
    }
}