夜風のMixedReality

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

Unityでフェイズシフトシェーダーをつくる その4 ShaderLabでの実装

本日はShader枠です。

先日ShaderGraphでガンダムSEEDの作品中に登場する架空の技術であるフェイズシフト装甲のシェーダーを作成しました。

redhologerbera.hatenablog.com

本日は、ShaderLabのコードで再現していきます。

〇ShaderLabでフェイズシフトシェーダーを作る

まずはコアとなるグレースケール表現をShaderLabで実装します。

グレースケールについてのおさらいですが、基本的にShaderではRGBA(赤、緑、青、透明度)の値が出力されます。

 色ではなく画素の発光のため光の三原色の原理が使用できますが、白黒を表現したい場合はRGBの値がそろえばよいです。

 よってRGBのそれぞれの成分を足し合わせ3分割した値をそれぞれの成分に代入することでグレースケールを再現できます。

 しかしShaderGraphで実装した際に発生した問題でもありますが、人間の感覚として、赤、緑、青を白黒で見る場合一様には見えず、赤は青より明るく見えます。

 これを再現するためには各成分にバイアスをかけたうえで足し合わせ分割する必要があります。

 具体的には次のようになります。

VisualGrayscale = 0.299*R+0.587*G+0.114*B

 これらの情報を用いてShaderLabでグレースケールを行うシェーダーを書いていきます。

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                float sumComponent = col.r * 0.299 + col.g * 0.587 + col.b * 0.114;

                col = float4(sumComponent, sumComponent, sumComponent,1) * (1 - _Power) + float4(col.r, col.g, col.b,1) * _Power;
                return col;
            }

またここで_Powerの変数はマテリアルプロパティから操作できるようにしたいのでプロパティブロックの改修もします。

    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Power ("Power",range(0,1) )= 1
    }

range型として指定することでプロパティでスライダーとして扱うことができるようになります。

これによって調整可能なグレースケールをShaderLabでも実装できました。

本日は以上です。

〇コード全文

Shader"Unlit/PSshader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Power ("Power",range(0,1) )= 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Power;

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

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                float sumComponent = col.r * 0.299 + col.g * 0.587 + col.b * 0.114;

                col = float4(sumComponent, sumComponent, sumComponent,1) * (1 - _Power) + float4(col.r, col.g, col.b,1) * _Power;
                return col;
            }
            ENDCG
        }
    }
}