Shader "Unlit/outLine"
{
//属性
Properties{
_RimColor("RimColor", Color) = (1,1,1,1)
_RimPower("RimPower", Range(1.0, 5.0)) = 1
}
//子着色器
SubShader
{
Pass
{
//定义Tags
Tags{ "RenderType" = "Opaque" }
CGPROGRAM
//引入头文件
#include "Lighting.cginc"
//定义Properties中的变量
fixed4 _RimColor;
float _RimPower;
//定义结构体:vertex shader阶段输出的内容
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
//在vertex shader中计算观察方向传递给fragment shader
float3 worldViewDir : TEXCOORD2;
};
//定义顶点shader,参数直接使用appdata_base(包含position, noramal, texcoord)
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
//顶点转化到世界空间
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//可以把计算计算ViewDir的操作放在vertex shader阶段,毕竟逐顶点计算比较省
o.worldViewDir = _WorldSpaceCameraPos.xyz - worldPos;
return o;
}
//定义片元shader
fixed4 frag(v2f i) : SV_Target
{
//归一化法线,即使在vert归一化也不行,从vert到frag阶段有差值处理,传入的法线方向并不是vertex shader直接传出的
fixed3 worldNormal = normalize(i.worldNormal);
//以下为本篇主题:计算RimLight
//把视线方向归一化
float3 worldViewDir = normalize(i.worldViewDir);
//计算视线方向与法线方向的夹角,夹角越大,dot值越接近0,说明视线方向越偏离该点,也就是平视,该点越接近边缘
float rim = 1 - saturate(dot(worldViewDir, worldNormal));
//计算rimLight
fixed3 rimColor = _RimColor * pow(rim, _RimPower);
return fixed4(rimColor,1);
}
//使用vert函数和frag函数
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
//前面的Shader失效的话,使用默认的Diffuse
FallBack "Diffuse"
}
当你想将颜色值规范到0~1之间时,你可能会想到使用saturate函数(saturate(x)的作用是如果x取值小于0,则返回值为0。如果x取值大于1,则返回值为1。若x在0到1之间,则直接返回x的值.)