原理:真实世界中,除了金属之外其它物质,视线垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显。
那么如果此时用一个1-减去这个反射值,便会将结果反过来,中间的暗,而外部会相对较亮。
同时,想有边缘外发光的效果,那么还得使用透明渲染通道和渐变,便会得到如下效果:
![](https://img.haomeiwen.com/i13721461/4ce898c4dc903822.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
}
}
}
结果:
![](https://img.haomeiwen.com/i13721461/5a279bd8f5c7cf1f.png)
![](https://img.haomeiwen.com/i13721461/a23d0129b60e4fb0.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
}
}
}
![](https://img.haomeiwen.com/i13721461/6d972a55462e714d.png)
网友评论