基于SDF的光照效果

发布时间 2023-10-20 18:00:29作者: 君莫笑-93

基于SDF的光照效果

好久没写博客了,怠惰了,就当爬了一步

原神二次元风格面部渲染

效果

Show me the code

Shader "Unlit/SDF"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
        _SdfTex ("SdfTex", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Tags { "LightMode"="ForwardBase" }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float4 _Color;
            sampler2D _MainTex;
            sampler2D _SdfTex;
            float4 _MainTex_ST;
            float4 _SdfTex_ST;

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

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

                //SDF
                float4 Left_tex = tex2D(_SdfTex, i.uv);
                float4 Right_tex = tex2D(_SdfTex, float2(1-i.uv.x, i.uv.y));
                float3 lightDir = _WorldSpaceLightPos0.xyz; //光线入射向量
                float3 RightSide = UnityObjectToWorldDir(float4(1.0,0.0,0.0,1.0)); //世界空间下右向量
                float is_right = dot(lightDir.x, RightSide.x); //光线是否在右边?
                float4 shadow = is_right > 0 ? Right_tex : Left_tex; //采样的阈值

                float3 forward = UnityObjectToWorldDir(float4(0.0,0.0,1.0,1.0));
                float reflect_val = -0.5 * dot(forward, lightDir) + 0.5; //计算得到的阈值
                float is_shadow = shadow < reflect_val ? 1:0; //比较两者,判断是否在阴影内

                float4 halfShadow = 0.5 * is_shadow + 0.5;
                return col * _Color* halfShadow;
            }
            ENDCG
        }
    }
}