ムラサメ研究ブログ

主にゲームやプログラミングのログ

UNITYことはじめ~ShaderLab あたり

UNITY歴

実はあまり触ってない。プラグイン書く仕事はしたけど C++バインディングしたり、そんなのだし 一応簡単に画面を触るけど 正直表面すら理解してないので はじめてUNITYをちゃんと勉強する

幸いなことに、仕事でUNITYを使う機会があり、今回は深い部分を調査する R&D案件だ

ShaderLab

なぜ最初にShaderか? 一般的に一番難しそうではないか? だからこそ、ここを理解する間には UNITYの全部が理解できるはずである なんせ 心臓部であるので

ShaderLabって?

基本的に HLSLである。一部セマンティクスや型が違ったりするけど そのHLSLをラップして、 DirectX9の FXファイルのような感じで、パスを制御したり色々できる

意外と機能がおおいので ゆっくり勉強する

基礎構文とかはヘルプみて

Unity - マニュアル: シェーダーリファレンス

シェーダーの種類

サーフェースシェーダ、頂点シェーダとフラグメントシェーダ、固定関数シェーダ の3個がある 固定関数シェーダーは ご存知DirectX9以前にあったやつで、今の時代は使う事はないだろう

頂点シェーダとフラグメントシェーダは 一般的なシェーダーで ご存知のもので、 想像通りのものである ドメインシェーダ、ハルシェーダ、ジオメトリシェーダ、コンピュートシェーダも記述できる

問題のサーフェースシェーダだが、結論からいうと 頂点シェーダとフラグメントシェーダを簡単に書くものである pragmaで Lambertとか指定すると、自動的に 頂点シェーダとフラグメントシェーダを生成してくれているようだ もちろん、細かい制御は出来ないので その時は自力で書こう

Aboutシェーダ

細かいのはヘルプ見てもらうとして 頂点&フラグメントシェーダのサンプルを

Shader "Unlit/SimpleUnlitTexturedShader"
{
    Properties
    {
        // we have removed support for texture tiling/offset,
        // so make them not be displayed in material inspector
        [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
    }

    SubShader
    {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"               
            }
            Cull Back

            CGPROGRAM
            // use "vert" function as the vertex shader
            #pragma vertex vert
            // use "frag" function as the pixel (fragment) shader
            #pragma fragment frag

            // vertex shader inputs
            struct appdata
            {
                float4 vertex : POSITION; // vertex position
                float2 uv : TEXCOORD0; // texture coordinate
            };

            // vertex shader outputs ("vertex to fragment")
            struct v2f
            {
                float2 uv : TEXCOORD0; // texture coordinate
                float4 vertex : SV_POSITION; // clip space position
            };

            // vertex shader
            v2f vert (appdata v)
            {
                v2f o;
                // transform position to clip space
                // (multiply with model*view*projection matrix)
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                // just pass the texture coordinate
                o.uv = v.uv;
                return o;
            }
            
            // texture we will sample
            sampler2D _MainTex;

            // pixel shader; returns low precision ("fixed4" type)
            // color ("SV_Target" semantic)
            fixed4 frag (v2f i) : SV_Target
            {
                // sample texture and return it
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

Shader “Unlit/SimpleUnlitTexturedShader” シェーダー名を設定。UNITY Editorから参照するときの名前

Properties マテリアルで設定するパラメータ テクスチャとか色々

SubShader シェーダーの始まり

SubShader/Tags 不透明オブジェクト、半透明オブジェクト等 シェーダーの設定をKeyValue方式で設定

SubShader/Pass レンダリングパス カリングやZTestなども設定できる

SubShader/Pass/Name 他のシェーダーから呼ぶ時に指定する名前

SubShader/Pass/Tags シェーダーの設定をKeyValue方式で。 例えば “LightMode”=“ForwardBase" であれば、Forwardレンダリングの時に使われるパスである Deferred等複数のパスを作れば、その時のレンダリングモードに応じたパスを実行する

CGPROGRAM~ENDCG シェーダーの具体的な中身。だいたいHLSL

pragma vertex vert pragma fragment frag 頂点シェーダ、フラグメントシェーダを使う&関数名を設定。 サーフェースシェーダだとここが surfaceになる。 その他 pragmaは色々あるのでヘルプ参照

などなど

とりあえず ヘルプに詳しく書いている