その他
    ホーム技術発信DoRubyUnityのシェーダーについて

    Unityのシェーダーについて

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    Unityのシェーダーについて自分で調べたことをまとめました。

    はじめに

    どうもmotsuka です。
    今回はシェーダーを書いてみたくなったのでいろいろと調べてみたことをまとめてみたいと思います。

    シェーダーとは

    シェーダーとはシェーディング処理(陰影処理)を行うプログラムのことで、オブジェクトの頂点や色を変えるプログラムのことを指します。ポリゴンやテクスチャ等の画像をどのように画面に表示するかを決めるプログラムです。

    またUnityでは3つのシェーダーがあり、

    • 固定関数シェーダー
    • サーフェイスシェーダー
    • 頂点フラグメントシェーダー

    Unityでシェーダーを書くときこれらを使い分けて書く必要があります。
    これらを簡単に説明すると

    • 固定関数シェーダー
      これはプログラマブルシェーダーをサポートしていない古いハードウェア用のシェーダーです。またこのシェーダーは後述のPass句のみからなるシェーダになります。
    • サーフェイスシェーダー
      影やライティングを扱うときに書くシェーダーです。
    • 頂点フラグメントシェーダー
      オブジェクトの頂点を変更したあとに色を変更することのできるシェーダーです。子のシェーダーでは結構複雑なエフェクトなどを表現するときに使用します。

    これらUnityで動くすべてのシェーダーでShaderLabという書式で書かれます。
    これらの項目はまとめにURLが書いてあるので詳しく読みたい方はそちらをご覧ください。

    サンプルコード

    では、簡単なシェーダーを書いてみましょう

    今回は簡単な例として画面上に置かれた立方体の色を変えるプログラムを書いていきたいと思います。

    まず、プロジェクト内で右クリックをして Create -> Shader -> Standard Surface Shaderをクリックしてシェーダーを作ります。
    それをテキストエディタで開いてみましょう。

    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
           #pragma surface surf Standard fullforwardshadows
            #pragma target 3.0
            sampler2D _MainTex;
            struct Input {
                float2 uv_MainTex;
            };
            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
            UNITY_INSTANCING_BUFFER_START(Props)
            UNITY_INSTANCING_BUFFER_END(Props)
            void surf (Input IN, inout SurfaceOutputStandard o) {
                fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                o.Albedo = c.rgb;
                o.Metallic = _Metallic;
                o.Smoothness = _Glossiness;
                o.Alpha = c.a;
            }
            ENDCG
        }
        FallBack "Diffuse" }
    

    上のようなソースができたと思います。
    上から読んでいきましょう
    大きく分けて二つの枠に分けることができます。

    • Properties
      ここにはUnity側からシェーダーに渡したいものを記述します。
      簡単に言うと変数宣言の場所と思ってください。
      Unity側からのデータを任意の名前を付けて使えるようにする場所です。
      このソースでは、色のデータや表面のテクスチャなどのデータを渡しています。
      この項目はインスペクター上に表示され変更することができるものになります。
    • SubShader
      ここには実際にシェーダーの中身を書いていく場所です。
      CGPROGRAMが処理の始まりを示していて、ENDCGが処理の終わりを示しています。
      この句のメインの処理はsurf関数です。
      ここではinputをうけとり様々な処理をしてSurfaceOutputStandardに詰めるという処理になっています。またinputに何が渡ってくるかはその上に書いてあるstructにて記述してあります。

    ではこのソースを変えてこのシェーダーがついているオブジェクトの色を変えましょう。

    _Color (“Color”, Color) = (1,1,1,1)

    の行を下のように書き換えます。

    _Color (“Color”, Color) = (1,0,0,1)

    に変えて保存したシェーダーからマテリアルをつくって適当なオブジェクトにアタッチしてみてください。
    そうすると色が赤色に変わったことが確認できます。

    まとめ

    書いたことがなかったシェーダーですが、やってみるとあまり難しくなくさっくりとできる印象ですので皆さんもやってみてはいかがでしょうか?ですが、C#とは全く違う書き方や最初はよくわからないパラメータが多く出てくるので最初はきついかもしれませんが、慣れるとすんなり読めるようになるので皆さんもシェーダーを書いてみましょう。
    次は文字のアウトラインをシェーダーで書いてみたいですね。余裕があったらまた書きたいと思います。
    参考にしたURLを下にのせておくのでそこから読んでもらうと理解がより深まると思います。

    Unity Documentation シェーダーマニュアル
    https://docs.unity3d.com/ja/current/Manual/ShadersOverview.html

    Unity のシェーダの基礎を勉強してみたのでやる気出してまとめてみた
    http://tips.hecomi.com/entry/2014/03/16/233943