夜風のMixedReality

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

MRTKのWireFrameShaderを覗いてみる。 SubShaderブロック

本日は昨日に引き続きMRTKのShader学習枠です。

昨日はMRTKで提供されているWireFrameShaderのSubShaderブロックを見ていきました。

redhologerbera.hatenablog.com

redhologerbera.hatenablog.com

本日は Passブロック内をざっくり見ていきます。

〇 Passブロック

Passブロックはオブジェクトのレンダリング処理を記述する部分です。

Passブロック自体は複数記述可能ですがWireFrameShaderでは1つのPassブロックで構成されています。

Pass
        {
            Offset 50, 100

            CGPROGRAM
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #if defined(SHADER_API_D3D11)
            #pragma target 5.0
            #endif

            #include "UnityCG.cginc"

            float4 _BaseColor;
            float4 _WireColor;
            float _WireThickness;

            // Based on approach described in Shader-Based Wireframe Drawing (2008)
            // http://orbit.dtu.dk/en/publications/id(13e2122d-bec7-48de-beca-03ce6ea1c3f1).html

            struct v2g
            {
              ...
            };

            v2g vert(appdata_base v)
            {
               ...
            }

            // inverseW is to counteract the effect of perspective-correct interpolation so that the lines
            // look the same thickness regardless of their depth in the scene.
            struct g2f
            {
                ...
            };

            [maxvertexcount(3)]
            void geom(triangle v2g i[3], inout TriangleStream<g2f> triStream)
            { 
             ...
            }

            float4 frag(g2f i) : COLOR
            {
                ...               
            }
            ENDCG
        }

〇 CGPROGRAM ENDCG

ShaderのコードであるCg/HLSL言語はこの間に記述されます。

〇プラグマ文

         #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #if defined(SHADER_API_D3D11)
            #pragma target 5.0
            #endif

WireFrameShaderでは3つのShaderが定義されています。

          #pragma vertex vert

頂点シェーダーをvertと定義します。

頂点シェーダーはその名の通りメッシュの頂点を操作するShaderです。

            #pragma geometry geom

ジオメトリシェーダーをgeomと定義します。

ジオメトリシェーダーは頂点シェーダーから頂点情報を受け取り、面としての処理を行います。

 #pragma fragment frag

フラグメントシェーダーをfragと定義します。

フラグメントシェーダーは描画されるピクセル色を処理します。

   #if defined(SHADER_API_D3D11)
            #pragma target 5.0
            #endif

ShaderのAPIがD3D11の場合 ShaderTargetが5に指定されます。

HoloLens 2の場合はShaderAPIはD3D11なのでこれは有効になります。

redhologerbera.hatenablog.com

〇 include

 #include "UnityCG.cginc"

これはUnityCG.cgincを使用するという意味になります。

UnityCG.cgincはUnity側で提供されているもので、Shaderでよく使用されるデータの型が収められているファイルになります。ここから頂点やUVといったデータを受けとります。

またTex2D()など一部のUnityで提供される関数を使用する際に使用します。

自身で定義する場合はappdate_tなどの構造体を作成して使用します。

     struct v2g
            {
              ...
            };

            v2g vert(appdata_base v)
            {
               ...
            }

            // inverseW is to counteract the effect of perspective-correct interpolation so that the lines
            // look the same thickness regardless of their depth in the scene.
            struct g2f
            {
                ...
            };

            [maxvertexcount(3)]
            void geom(triangle v2g i[3], inout TriangleStream<g2f> triStream)
            { 
             ...
            }

            float4 frag(g2f i) : COLOR
            {
                ...               
            }

〇v2g構造体

頂点シェーダーから受け取ったデータをジオメトリシェーダーに渡すための構造体です。

慣例としてVertext to Geometryでv2gと書くようです。

〇頂点シェーダー

            v2g vert(appdata_base v)
            {
               ...
            }

頂点シェーダーでは頂点の座標などにかかわる処理を行います。

v2g vert(appdate_base v)UnityCG.cgincで定義されているappdate_baseからデータを受け取りそのデータをvとして使用しv2g構造体に返すという意味になります。

〇g2f構造体

       struct g2f
            {
                ...
            };

v2g構造体同様ジオメトリシェーダーで処理されたデータをフラグメントシェーダーで使用するためのデータとして格納します。(Geometry to fragment)

〇ジオメトリシェーダー

  [maxvertexcount(3)]
            void geom(triangle v2g i[3], inout TriangleStream<g2f> triStream)
            { 
             ...
            }

ジオメトリシェーダーでは頂点シェーダーから頂点情報を受け取り、複数の頂点から面を構成しメッシュとしての処理を行うことができます。

ここでは [maxvertexcount(3)]が受け取る頂点数を指定します。この場合3つの頂点を受け取っています。

triangle v2g i[3]が入力データに相当し、v2g構造体から3つの配列を作成しtriangle(三角形)として扱うという意味になります。

inout TriangleStream triStreamが出力になり、g2f構造体に出力しています。

〇フラグメントシェーダー

      float4 frag(g2f i) : COLOR
            {
                ...               
            }

フラグメントシェーダーではg2f構造体から受け取ったデータをiとして使用し最終的に色情報として使用されるfloat4型で返されます。

以上がざっくりとしたPassブロックの中身です。