フェイクポイントライト

環境

Unity2021.2.18f1

概要

フェイクポイントライトの実装テストです。 法線を考慮してないシンプルなものです。

Hierarchy>3d Object >Sphareで球体モデルを生成して、マテリアルに設定します。

コード

Shader "Custom/FakePointLight"
{
    Properties{
        [HDR]_Color("Color", Color) = (1, 1, 1, 1)
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
        Pass
        {
            ZWrite Off
            Lighting Off
            Cull Front
            ZTest Always
            Blend SrcAlpha One

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

            half4 _Color;
            sampler2D _CameraDepthTexture;

            struct VSInput
            {
                float4 vertex : POSITION;
                float3 texcoord : TEXCOORD0;
            };
#define SSTOWS_TYPE0 1
            struct VSOut
            {
                float4 positionCS :SV_POSITION;
                float4 positionSS : TEXCOORD0;
#if SSTOWS_TYPE0
                float3 rayVS : TEXCOORD1;
#else
                float3 positionWS : TEXCOORD2;
#endif
                float radius : TEXCOORD3;
            };

            VSOut vert(VSInput v)
            {
                VSOut o;
                o.positionCS = UnityObjectToClipPos(v.vertex);
                o.positionSS = ComputeScreenPos(o.positionCS);
#if SSTOWS_TYPE0
                o.rayVS = UnityObjectToViewPos(v.vertex).xyz;
                o.rayVS.z *= -1;
#else
                o.positionWS = mul(unity_ObjectToWorld, v.vertex).xyz;
#endif
                o.radius = length(UNITY_MATRIX_M._m01_m11_m21) * 0.5;
                return o;
            }

            fixed4 frag(VSOut i) : Color
            {
#if SSTOWS_TYPE0
                const float far = _ProjectionParams.z;
                i.rayVS = i.rayVS * (far / i.rayVS.z);
                float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.positionSS.xy / i.positionSS.w));
                float4 positionVS = float4(i.rayVS * depth, 1);
                float3 positionWS = mul(unity_CameraToWorld, positionVS).xyz;
#else
                float4 positionSS = i.positionSS / i.positionSS.w;
                float eyeDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, positionSS.xy));
                float3 cameraForwardDir = -UNITY_MATRIX_V._m20_m21_m22;
                float3 viewDirWS = normalize(UnityWorldSpaceViewDir(i.positionWS));
                float3 positionWS = ((eyeDepth * viewDirWS * (1.0 / dot(cameraForwardDir, viewDirWS))) + _WorldSpaceCameraPos);
#endif
                float len = length(positionWS - UNITY_MATRIX_M._m03_m13_m23);
                float power = 1.0 - smoothstep(0, 1, pow(saturate(len / i.radius), 0.5));
                //float power = 1.0 - smoothstep(0, 1, len / i.radius);
                return fixed4(_Color.rgb, _Color.a * power);
            }
            ENDCG
        }
    }
}

参考

bshishov/SimpleDecal.shader