夜風のMixedReality

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

UnityでShaderを勉強する その③ 実際にShaderの中身を見ていく

本日はShader勉強枠です。

前回実際にShaderの中身を見ていきました。

redhologerbera.hatenablog.com

今回はもっと中身を読み解いてShaderの構造をつかみます。

前回に引き続きShaderサンプルを見ながら勉強しています。

docs.unity3d.com

〇Diffuse SimpleShader

f:id:Holomoto-Sumire:20200331082511j:plain

 Shader "Example/Diffuse Simple" {
      SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float4 color : COLOR;
        };
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = 1;
        }
        ENDCG
      }
      Fallback "Diffuse"
    }

〇ShaderLabシンタックスを読み解く

前回UnityのShaderは二つの言語で記述されているといいましたが、サンプルのディフューズShaderのShaderLabシンタックスの部分を抜き取ると以下のようになります。

 Shader "Example/Diffuse Simple" {
      SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
     
        ENDCG
      }
      Fallback "Diffuse"
    }
〇Name
 Shader "Example/Diffuse Simple" { }

ここでこのShaderの名前が定義されています。

Unity側見てみると

f:id:Holomoto-Sumire:20200330130149j:plain

Exampleの中に

f:id:Holomoto-Sumire:20200330130220j:plain

Diffuse Simpleが作成されています。

つまり

 Shader "XX/〇〇/▽▽" { }

という名前を付けるとしたらXXというカテゴリーグループのさらに○○というカテゴリーグループに▽▽という名前でShaderが定義されます。

〇SubShader

次にSubShader内部を見ていきます。

 SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
     
        ENDCG
      }

〇Tags

        Tags { "RenderType" = "Opaque" }

Tagsではどのようにレンダリング(描画)を行うかを指定します。

以下のように記述することで複数持つことも可能です。

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

Diffuse SimpleではRenderTypeをOpaque(不透明)にして描画を行うように指定しています。(RGBA(Red Green Blue Alpha)のおそらく透明度を表すA値を無視する設定)

docs.unity3d.com

〇CGPROGRAM~ENDCGの中身を見る

 #pragma surface surf Lambert
        struct Input {
            float4 color : COLOR;
        };
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = 1;
        }
〇Pragma構造体
#pragma surface surf Lambert

#pragma文ではどのようにShaderをコンパイル(出力)するかを定義します。

#pragma文は次のように記述します。

pragma surface surfaceFunction lightModel [optionalparams]

Diffuse Sampleではsurfという関数でLambertというライティングモデルを使用します。

ライティングモデルはUnityで提供される光をどのように当てるか計算をする関数です。

docs.unity3d.com

surfという関数はその下で定義されています。

      void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = 1;
        }

Input から受け取りSurfaceOutputで出力するという形になるようです。

SurcaseOutputというのはUnityのレファレンスによると次のような定義を含んでいるようです

struct SurfaceOutput
{
    fixed3 Albedo;  // ディフューズ色
    fixed3 Normal;  // 書き込まれる場合は、接線空間法線
    fixed3 Emission;
    half Specular;  //  0..1 の範囲のスペキュラーパワー
    fixed Gloss;    // スペキュラー強度
    fixed Alpha;    // 透明度のアルファ
};

docs.unity3d.com

ここでAlbed(アルベド)は反射光のことで0にすると反射しない=真っ黒になります。

f:id:Holomoto-Sumire:20200331082511j:plain
Albedo=1

f:id:Holomoto-Sumire:20200331082607j:plain
Albedo=0

ではInputは?というとsurf関数の直下にあります。

〇Input構造体
        struct Input {
            float4 color : COLOR;
        };

Input構造体はShaderの処理で必要とされるテクスチャ情報が記述されます。

このディフューズShaderではテクスチャは使用していませんが、テクスチャを使用する場合はテクスチャ情報

ここでは、カラーを指定しています。

Inputで記述したカラーの情報がSurf関数でAlbedo=1として処理されているようです。

docs.unity3d.com

〇Fallback

最後にこのShaderがデバイスで実行できなかった場合DiffuseのShaderが代わりに呼ばれます。

以上がサンプルのディフューズShaderになります。

このShaderがディフューズShaderであることを決めているのは

        #pragma surface surf Lambert

のライティングモデルであるLambertであるようです。

次回からサンプルに従い勉強しながらこのShaderを変形させていきます。