七、游戏表现:2、边缘发光2

2021-03-20  本文已影响0人  GameObjectLgy

原理:真实世界中,除了金属之外其它物质,视线垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显。
那么如果此时用一个1-减去这个反射值,便会将结果反过来,中间的暗,而外部会相对较亮。
同时,想有边缘外发光的效果,那么还得使用透明渲染通道和渐变,便会得到如下效果:


2.png

下面推演效果过程:
1、得到基础的边缘光

Shader "MyLearn02/EdgeLight2"
{
    Properties
    {
        _RimRange("RimRange 边缘光范围",Range(0.0,10)) = 1.0
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        LOD 100

        Pass
        {
            ZWrite Off
            Blend SrcAlpha One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float4 normal : NORMAL; // 法线信息 Get✔

            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 posCS : SV_POSITION; 
                float4 posWS : TEXCOORD1; // 世界空间顶点位置
                float3 nDirWS : TEXCOORD2; // 世界空间法线方向
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _RimRange;
            
            v2f vert (appdata v)
            {
                v2f o = (v2f)0;
                o.uv = v.uv;
                o.posCS = UnityObjectToClipPos(v.vertex); // 变换顶点位置 OS>CS
                o.posWS = mul(unity_ObjectToWorld, v.vertex); // 变换顶点位置 OS>WS
                o.nDirWS = UnityObjectToWorldNormal(v.normal); // 变换法线方向 OS>WS
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                //1、向量准备
                float3 nDir = i.nDirWS;//法线方向
                float3 lDir = _WorldSpaceLightPos0.xyz;//光方向
                float3 rDir = reflect(-lDir, nDir);//光反射方向
                float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);//观察方向

                //2、中间量准备:准备点击结果
                float ndotl = dot(nDir, lDir);
                //float vdotr = dot(vDir, rDir);
                float vdotr = dot(vDir, nDir);
                //3、光照模型Fresnel = pow(1-ndotv,powVal)。
                //1-ndotv:中间暗,边缘亮;
                //power:套一个power控制边缘亮的范围;
                half fresnel = 1.0 - saturate(vdotr);//菲尼尔
                half temp_fresnel = pow(fresnel, _RimRange);
                //4、返回结果
                return float4(temp_fresnel, temp_fresnel, temp_fresnel, 1);
            }
            ENDCG
        }
    }
}

结果:


2_1.png
3.png

2、控制边缘光的内发光颜色和外发光颜色,以及范围

Shader "MyLearn02/EdgeLight3"
{
    Properties
    {
        _RimRange("RimRange 边缘光范围",Range(0.0,10)) = 1.0
        _MainTex("Texture", 2D) = "white" {}
        _InnerColor("Inner Colorn 内发光颜色",Color) = (0.0,0.0,0.0,0.0)
        _InnerAlpha("Inner Alpha 内发光透明度",Range(0.0,1.0)) = 0.0
        _RimColor("Rim Color 边缘光颜色",Color) = (1,1,1,1)
        _RimIntensity("Rim Intensity 边缘光强度",Range(0.0,10)) = 1.0
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        LOD 100

        Pass
        {
            ZWrite Off
            Blend SrcAlpha One
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float4 normal : NORMAL; // 法线信息 Get✔

            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 posCS : SV_POSITION; 
                float4 posWS : TEXCOORD1; // 世界空间顶点位置
                float3 nDirWS : TEXCOORD2; // 世界空间法线方向
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _RimRange;
            float4 _InnerColor;
            float4 _RimColor;
            float _InnerAlpha;
            float _RimIntensity;
            
            v2f vert (appdata v)
            {
                v2f o = (v2f)0;
                o.uv = v.uv;
                o.posCS = UnityObjectToClipPos(v.vertex); // 变换顶点位置 OS>CS
                o.posWS = mul(unity_ObjectToWorld, v.vertex); // 变换顶点位置 OS>WS
                o.nDirWS = UnityObjectToWorldNormal(v.normal); // 变换法线方向 OS>WS
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                //1、向量准备
                float3 nDir = i.nDirWS;//法线方向
                float3 lDir = _WorldSpaceLightPos0.xyz;//光方向
                float3 rDir = reflect(-lDir, nDir);//光反射方向
                float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);//观察方向

                //2、中间量准备:准备点击结果
                float ndotl = dot(nDir, lDir);
                //float vdotr = dot(vDir, rDir);
                float vdotr = dot(vDir, nDir);
                //3、光照模型Fresnel = pow(1-ndotv,powVal)。
                //1-ndotv:中间暗,边缘亮;
                //power:套一个power控制边缘亮的范围;
                half fresnel = 1.0 - saturate(vdotr);//菲尼尔
                half temp_fresnel = pow(fresnel, _RimRange);
                //4、返回结果
                half emiss = tex2D(_MainTex, i.uv).r;
                emiss = pow(emiss, 5.0);//自发光
                float4 final_fresnel = saturate(emiss + temp_fresnel);
                half3 final_rim_color = lerp(_InnerColor.xyz, _RimColor.xyz * _RimIntensity, final_fresnel);
                half final_rim_alpha = final_fresnel;
                float final_alpha = saturate(final_rim_alpha  + _InnerAlpha);
                return float4(final_rim_color, final_alpha);
            }
            ENDCG
        }
    }
}

4.png
上一篇 下一篇

猜你喜欢

热点阅读