Unity 星球边光渲染

策划给的参考图:

在这里插入图片描述

这是游戏中的效果图:

在这里插入图片描述

说明:

原理很简单 菲列尔 + 兰伯特,控制边光范围和强度。

但是我们美术有个特殊需求:要求星球在任意位置,边光的范围都保持一致(场景也是移动的)。

如果仅仅使用普通的兰伯特,星球的受光范围在平面上是变化的。如下图:
在这里插入图片描述
这个情况不符合美术需求,原因是在不同位置看到的法线分布不一样。

为了纠正这个问题可以使用 N 叉乘 V 来作为新的法线使用, 这样能得面向视角的法线。

Shader代码如下:

Shader "WingFighter/ShiftLight"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _LightDir ("LightDir", Vector) = (1,1,0,0) 
        _RimColor ("RimColor", Color) = (1,1,1,1)
        _RimIntensity ("RimIntensity", range(0,100)) = 1 
        _RimPower("RimPower", float) = 1
        _RimLambertPower("RimLambertPower", float) = 1
        _RimLambertOffset("RimLambertOffset", range(0,1)) = 0
        _ShadowStrength("ShadowStrength", range(0,0.5)) = 0.1
        
        [Header(CommonRim)]
        _CommonRimColor ("CommonRimColor", Color) = (1,1,1,1)
        _CommonRimPower("CommonRimPower", float) = 1
        _CommonRimIntensity("CommonRimIntensity", float) = 1

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityShaderVariables.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldNormal : TEXCOORD2;
                float4 worldPos : TEXCOORD3;
                float4 distance : TEXCOORD4;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _LightDir;
            float4 _RimColor;
            half _RimPower;
            half _RimIntensity;
            half _RimLambertPower;
            half _RimLambertOffset;
            half _ShadowStrength;
            half _CommonRimIntensity;
            
            float4 _CommonRimColor;
            half _CommonRimPower;
           

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                
                float3 viewPos = UnityObjectToViewPos(v.vertex);
                float3 centerViewPos = UnityObjectToViewPos(float4(0,0,0,0));
                o.distance.x = distance(viewPos, centerViewPos); 
                
                return o;
            }
            

            fixed4 frag (v2f i) : SV_Target
            {
                float3 mainColor = tex2D(_MainTex, i.uv);
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                
                float3 newNormal = cross(i.worldNormal, worldViewDir);
                float NDotL = dot( newNormal, _LightDir);
                float halfLambert = NDotL * 0.5 + 0.5;
                float adjustedLabmbert = saturate(halfLambert - _RimLambertOffset);
                float halfLambertPow = pow(adjustedLabmbert, _RimLambertPower); 
                
                half NDotV = dot(i.worldNormal, worldViewDir);
                half rimlight = pow(1 - NDotV, _RimPower);
                float rimIntensity = rimlight * _RimIntensity * halfLambertPow;
                half commonRimStrength = pow(1 - NDotV, _CommonRimPower);
                half3 commonRim = mainColor * rimlight * commonRimStrength * _CommonRimColor * _CommonRimIntensity;
                
                half3 finalColor =  mainColor * (_ShadowStrength + rimIntensity * _RimColor) + commonRim.rgb;
                return half4(finalColor, 1);
            }
            ENDCG
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值