Unity Shader 边缘光

RinLight 边缘光

核心:

根据点积来判断模型的边缘,在模型的边缘位置着色一层颜色光。

着色边缘光原理:

通过视角方向点积法线方向得到的结果,来判断该片元是否处于模型边缘,点积得到的值在0-1之间,当结果等于0时说明该片元处于模型的边缘,这个时候,视角方向与法线方向相互垂直,与切线方向共线,可以理解为,当视角方向与法线垂直,或与切线共线时,说明该片元为边缘。反之,结果越靠近1片元则越处于模型中心。因此我们可以我们可以根据点积的值来计算边缘光的强弱。

边缘光核心计算公式:

float rim =1-saturate(dot(worldNormalDir,WorldViewDir));
float3 rimColor=_RimColor*pow(rim,1/_RimPower);

开启边缘光效果:在这里插入图片描述

Shader源码:
漫反射边缘光

Shader "Unity/RimLight"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Diffuse("Diffuse",Color) =(1,1,1,1)
        //边缘光颜色
        _RimColor("RimColor",Color)=(1,1,1,1)
        _RimPower("RimPower",Range(0,1)) =0
        
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        Pass
        {
            CGPROGRAM 
            #pragma vertex vert
            #pragma fragment frag 
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _Diffuse;
            float4 _RimColor;
            float _RimPower;

            struct v2f
            {
                float4 vertex:SV_POSITION;
                float2 uv:TEXCOORD0;
                float3 worldLightNormal:TEXCOORD1;
                float3 worldNormal:TEXCOORD2;
                float3 worldViewNormal:TEXCOORD3;
            };

            v2f vert(appdata_base v)
            {
                v2f o;
                o.vertex=UnityObjectToClipPos(v.vertex);
                o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
                float3 worldPos=mul(unity_ObjectToWorld,v.vertex);
                //获取世界法线 视角方向  光源防线
                o.worldLightNormal= UnityWorldSpaceLightDir(worldPos);
                o.worldViewNormal=UnityWorldSpaceViewDir(worldPos);
                o.worldNormal=UnityObjectToWorldNormal(v.normal);
                return o;
            };

            fixed4 frag(v2f i):SV_TARGET
            {
                //归一化法线 因为从顶点着色器到片源着色器阶段有差值处理,所以在顶点着色器归一化并不是最好的选择
                float3 worldNormalDir=normalize(i.worldNormal);
                float3 WorldLightDir=normalize(i.worldLightNormal);
                float3 WorldViewDir=normalize(i.worldViewNormal);

                float3 texColor=tex2D(_MainTex,i.uv).rgb;

                float3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb*texColor.rgb;
                //计算半兰伯特漫反射
                float3 diffuse=_LightColor0.rgb*_Diffuse.rgb*texColor.rgb*(dot(worldNormalDir,WorldLightDir)*0.5+0.5);
                
                //计算边缘光颜色 Dot结果为0-1之间 结果越靠近0说明越靠近边缘颜色越重,故1-Dot
                float rim =1-saturate(dot(worldNormalDir,WorldViewDir));
                //计算RimLight
                float3 rimColor=_RimColor*pow(rim,1/_RimPower);
                //输出片源颜色
                float3 color=diffuse+ambient+rimColor;

                return fixed4(color,1);
            };
            ENDCG
        }
    }
    Fallback "Diffuse"
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铸梦xy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值