夜風のMixedReality

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

ゼロから始めるUnityShader開発 第五章 発光するシェーダーを書く

本日はShader枠です。

今回はエフェクトなどによく使用される発光表現を行います。

〇UnityShaderにおける発光表現

Unityでは発光表現を行うことができます。

 発光表現にはグロー効果がつきものですが、これはPostProcessing(後処理)と呼ばれる処理を行うことで実装されます。

 PostProcessingを使用しない場合は次のように淡く色づく程度で空間的な作用は行われません。

 

Shaderでは最終的な色の出力はfloat4型のRGBAで返されますが、通常の色は0~1であらわされています。

 この時に1を超えた値が発光色として返されます。

 この1を超えた値をHigh Dynamic Range(HDR)という幅であらわします。

 まずは発光色としてHDRの色を表すためにPropertiesブロックに_EmissionColorを定義します。  

    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor("Color" ,color) = (1,1,1,1)
        
        [HDR]
        _EmissionColor("EmissionColor",color) = (0,0,0,0)
    }

 HDRのアトリビュートをつけることでHDRを扱うことができるプロパティを使用できます。

 HDRのカラープロパティはIntensityと呼ばれるパラメータを使用できます。

次に発光は1を超えた値…つまり加算によって行われるので_EmissionColorを出力色に追加します。

            float4 frag (v2f i) : SV_Target
            {
                float4 col =   SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv)  *_MainColor;
                //Light.hlslで提供されるUnityのライトを取得する関数
                Light lt = GetMainLight(i.shadowCoord);

                //ライトの向きを計算
                float strength = dot(lt.direction, i.normalWS);
                float4 lightColor = float4(lt.color, 1)*(lt.distanceAttenuation * lt.shadowAttenuation);
                col = col* lightColor*strength +_EmissionColor;//追加
                return col;
            }

 これによって発光するシェーダーを記述することができます。

〇シェーダー全文

Shader "Unlit/TutorialEmissionShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MainColor("Color" ,color) = (1,1,1,1)
        
        [HDR]
        _EmissionColor("EmissionColor",color) = (0,0,0,0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include  "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
            
            struct appdata
            {
                float4 vertex : POSITION;
                half3 normal: NORMAL;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
            float4 vertex : SV_POSITION;
            float3 normalWS : TEXCOORD1;
            float4 shadowCoord : TEXCOORD3;
                float2 uv : TEXCOORD0;
            };

            TEXTURE2D(_MainTex);
            SAMPLER(sampler_MainTex);
            float4 _MainColor;
            float _Alpha;
            float _AlphaThreshold;
            float4 _EmissionColor;
            
            v2f vert (appdata v)
            {
                v2f o;
               // o.vertex = TransformObjectToHClip(v.vertex);
                //面の法線を取得、ライトの当たる向きを計算
                VertexNormalInputs normal = GetVertexNormalInputs(v.normal);
                o.uv = v.uv;
                o.normalWS = normal.normalWS;
                VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
                o.vertex = vertexInput.positionCS;
                o.shadowCoord = GetShadowCoord(vertexInput);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float4 col =   SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv)  *_MainColor;
                //Light.hlslで提供されるUnityのライトを取得する関数
                Light lt = GetMainLight(i.shadowCoord);

                //ライトの向きを計算
                float strength = dot(lt.direction, i.normalWS);
                float4 lightColor = float4(lt.color, 1)*(lt.distanceAttenuation * lt.shadowAttenuation);
                col = col* lightColor*strength +_EmissionColor;
                return col;
            }
            ENDHLSL
        }
    }
}