🌈

そろそろShaderをやるパート36 Directional Light、環境光を反映する

2021/06/06に公開

そろそろShaderをやります

そろそろShaderをやります。そろそろShaderをやりたいからです。
パート100までダラダラ頑張ります。10年かかってもいいのでやります。
100記事分くらい学べば私レベルの初心者でもまあまあ理解できるかなと思っています。

という感じでやってます。

※初心者がメモレベルで記録するので
 技術記事としてはお力になれないかもしれません。

下準備

下記参考
そろそろShaderをやるパート1 Unite 2017の動画を見る(基礎知識~フラグメントシェーダーで色を変える)

デモ

前回のDiffuseにDirectional Lightと環境光を反映したShaderです。

【参考リンク】:そろそろShaderをやるパート35 Diffuse(拡散反射)

Shaderサンプル

Shader "Custom/Diffuse"
{
    Properties
    {
        _MainColor ("Main Color", Color) = (0, 0, 0, 1)
        _DiffuseShade("Diffuse Shade",Range(0,1)) = 0.5
    }

    SubShader
    {
        Tags
        {
            "LightMode"="ForwardBase"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            fixed4 _MainColor;
            float _DiffuseShade;

            struct appdata
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                float4 pos:SV_POSITION;
                float3 worldNormal:TEXCOORD0;
                float3 ambient : COLOR0; //環境光
            };

            //頂点シェーダー
            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                //法線方向のベクトル
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                o.ambient = ShadeSH9(half4(o.worldNormal,1));
                return o;
            }

            //フラグメントシェーダー
            fixed4 frag(v2f i) : SV_Target
            {
                //1つ目のライトのベクトルを正規化
                float3 L = normalize(_WorldSpaceLightPos0.xyz);
                //ワールド座標系の法線を正規化
                float3 N = normalize(i.worldNormal);
                //ライトベクトルと法線の内積からピクセルの明るさを計算 ランバートの調整もここで行う
                fixed4 diffuseColor = max(0, dot(N, L) * _DiffuseShade + (1 - _DiffuseShade));
                //色を乗算
                fixed4 finalColor = _MainColor * diffuseColor * _LightColor0 * float4(i.ambient,0);
                return finalColor;
            }
            ENDCG
        }
    }
}

"Lighting.cginc"

"Lighting.cginc"を追加することでDirectional Lightの色を利用できます。
_LightColor0がDirectional Lightの色に該当します。
Tags { "LightMode"="ForwardBase" }も必要なようです。

もし、複数ライトがある場合は2Pass目以降に
Tags { "LightMode"="ForwardAdd" }を記述すれば取得が可能なようです。

【参考リンク】:【Unity】【シェーダ】Forward Renderingで複数のライトを取り扱う

環境光

環境光はo.ambient = ShadeSH9(half4(o.worldNormal,1));
の箇所でRGBを取得しています。

【参考リンク】:Unity の Shader で環境光を得る

参考リンク

UnityでForwardのライトに対応したLambert反射モデルのシェーダを作成する
[Unity] Cgでのライティングについてメモ
【Unityシェーダ入門】ランバート拡散照明モデルを試す
[Unity]シェーダでランバート反射
Unityでシェーダー描いてみたい
Unityシェーダー】よく使う手法・計算まとめ

Discussion