ノートの端の書き残し

UnityやらC#やら。設計が得意かもしれない。

シェーダのお勉強、基礎まとめ

Unityでのシェーダを勉強中なので、備忘録も含めて学んだことのメモです。

シェーダは何から勉強したらいいのかわからないとよく言われ、事実僕もちょっと前まで何の知識も無かったので、そこからどうやって勉強したのかとか、初心者目線で書ければいいかなと思います。

そもそもシェーダって何してるの? という疑問を解消するには、レンダリングパイプラインというものについて調べるのが最も正しいのではないかと思います。レンダリングパイプラインの説明は調べればそれはもう色々と出てきますが、この辺とか最初に触れる部分を特に丁寧に説明していて良いのではないでしょうか。

yttm-work.jp

実際にUnityでシェーダを書いてみる

とりあえずシェーダを書いてみましょう。
完璧に理解するよりも先にいじって動かすのがプログラミング学習です。
あ、用いているUnityのバージョンはUnity2018.3.5f1です。

まず、シェーダファイルを作成します。
プロジェクトタブで
Create -> Shader -> Standerd Surface Shader f:id:u_osusi:20190310184013p:plain

名前はTestとでもしましょうか。

このような中身のシェーダファイルが生成されました。

Shader "Custom/Test"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

なんだこれという感じですね。
これはライティングも意識した場合のシェーダですが、最初からこんなのいじるのは良くないので、 とりあえず上のデフォルトスクリプトのことは完全に忘れて、以下のように書き直してください。

Shader "Custom/Test"
{
    Properties
    {
    }
    SubShader
    {
        Pass{
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

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

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

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

            fixed4 frag(v2f i) : SV_Target
            {
                return fixed4(i.uv.x, i.uv.y, 0, 0);
            }
            ENDCG
        }
    }
}

超シンプル、というわけではないですが、かなりマシになりましたね。 実はシェーダ作成の時点でUnlitシェーダやImageEffectシェーダを選んでいると似た感じのデフォルトスクリプトが生成されます。
なんかUnityはsurfaceシェーダをお勧めしてくるんですが、ちゃんと理解せずに使うものではないと思います……
さて、これをQuadで実行すると f:id:u_osusi:20190311002929p:plain このようになります。
QuadはHierarchy上で右クリック -> 3D Object -> Quadで作成できます。 シェーダはそのままでは利用できず、Materialというものを作ってあげる必要があります。 Projectタブの、先ほど作成したTestシェーダの上で右クリック -> Create -> MaterialとするとTestシェーダのMaterialが作成されます。 作成したMaterialをQuadまでドラッグすると(C#スクリプトのときと同じように)完了。 上図にようになるはずです。
いくつかのシェーダ入門記事を見ていて確信したのですが、この赤緑のシェーダは
シェーダ界におけるHello World.
です。

このHello World.の解説はまた次の記事で行います。
お読みいただいてありがとうございました。