使用UnityShader实现外发光效果
实现原理------------------------------------------------------------------------------------
法线和视角向量的点积值为 Cos(angle), 夹角越大,值越小;
Color * (1- Cos(angle))可以模拟边缘亮内部暗的现象;
Color * (1- Cos(angle))^power, 使用指数控制边缘光的范围;
效果展示-------------------------------------------------------------------------------------------------------
Shader "zclShader/边缘光Shader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//控制外发光的颜色
_RimColor("_RimColor",Color) = (0,0,1,0)
//控制外发光的范围
_RimPower("_RimPower",Range(1,10)) = 1
//控制外发光的强度
_RimStrength("_RimStrength",Range(1,10)) = 4
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 normal:NORMAL;
float3 m_viewDir:TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _RimColor;
float _RimStrength;
float _RimPower;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = v.normal;
o.m_viewDir = ObjSpaceViewDir(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 normal = normalize(i.normal);
float3 m_viewDir= normalize(i.m_viewDir);
float Rim = 1 - saturate(dot(normal, m_viewDir));
Rim = pow(Rim,_RimPower);
float4 addColor = Rim * _RimColor *_RimStrength;
fixed4 col = tex2D(_MainTex, i.uv);
col += addColor;
return col;
}
ENDCG
}
}
}
使用纹理贴图实现外发光
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
//法线的投影在 (-1,1)之间
//放在顶点shader里面计算,模型缩放影响外发光的表现
o.uv.zw = mul(UNITY_MATRIX_MV, v.normal).xy * 0.5 + 0.5;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv.xy);
fixed4 RimColor = tex2D(_RimTex, i.uv.zw); //对发光纹理采样
return col + RimColor*fixed4(1,0,0,1);
}
在片元中计算
fixed4 frag (v2f i) : SV_Target
{
float2 rimUV = mul(UNITY_MATRIX_MV, normalize(i.normal)).xy * 0.5 + 0.5;
fixed4 col = tex2D(_MainTex, i.uv);
fixed4 RimColor = tex2D(_RimTex, rimUV ); //对发光纹理采样
return col + RimColor*fixed4(1,0,0,1);
}
模型放大以后,法线的方向会发生变化,使用逆阵处理
fixed4 frag (v2f i) : SV_Target
{
float2 rimUV = mul(UNITY_MATRIX_IT_MV, normalize(i.normal)).xy * 0.5 + 0.5;
fixed4 col = tex2D(_MainTex, i.uv);
fixed4 RimColor = tex2D(_RimTex, rimUV ); //对发光纹理采样
return col + RimColor*fixed4(1,0,0,1);
}
免责声明:图片素材来源于Unity资源商店免费资源包,仅供学习使用
参考资料:https://edu.manew.com/my/course/443/material?type=material
参考书籍:冯乐乐《unityshader入门精要》
参考书籍:郭浩瑜,张鹤《unity3D shaderLab开发实战详解》