核心
积雪方向和法线进行点击,如果大于积雪厚度值则改变该片元的输出颜色为雪的颜色
效果图
卡通积雪场景效果图卡通场景效果图
Shader "Unlit/020"
{
Properties
{
_MainTex ("纹理", 2D) = "white" {}
_Diffuse("漫反射",Color) = (1,1,1,1)
_BumpMap("法线贴图",2D) = "while"{}
_BumpScale("法线强度",float) = 1
_Outline("轮廓粗细", Range(0,0.2)) = 0.1
_OutlineColor("轮廓颜色", Color) = (0,0,0,0)
_Step("离散化",Range(1,30))=1
_ToonEffect("卡通效果",Range(0,1))=0.5
_Snow("积雪厚度",Range(0,1)) = 0.5
_SnowColor("积雪的颜色",Color) = (1,1,1,1)
_SnowDir("积雪的方向",Vector) = (0,1,0)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
//调用上章所用到的描边ShaderPass进行描边
UsePass "Unlit/019/Outline"
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//宏开关设置
#pragma multi_compile __ SNOW_ON
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float4 uv : TEXCOORD0;
float4 T2W0 : TEXCOORD1;
float4 T2W1 : TEXCOORD2;
float4 T2W2 : TEXCOORD3;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Diffuse;
float _Step;
float _ToonEffect;
sampler2D _BumpMap;
float4 _BumpMap_ST;
float _BumpScale;
float _Snow;
float4 _SnowColor;
float4 _SnowDir;
v2f vert (appdata_tan v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
//求出世界(坐标\法线\副法线\切线
fixed3 worldPos = mul (unity_ObjectToWorld,v.vertex);
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal,worldTangent) * v.tangent.w;
//切线空间转世界空间矩阵
o.T2W0 = float4(worldTangent.x,worldBinormal.x,worldNormal.x,worldPos.x);
o.T2W1 = float4(worldTangent.y,worldBinormal.y,worldNormal.y,worldPos.y);
o.T2W2 = float4(worldTangent.z,worldBinormal.z,worldNormal.z,worldPos.z);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT;
//采样
fixed4 albedo = tex2D(_MainTex,i.uv);
//世界坐标
float3 worldPos = float3(i.T2W0.w,i.T2W1.w,i.T2W2.w);
//光源方向和视角方向
fixed3 lightDir = UnityWorldSpaceLightDir(worldPos);
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
//法线贴图
fixed4 packedNormal = tex2D(_BumpMap,i.uv.zw);
//切线空间法线
fixed3 tangentNormal = UnpackNormal(packedNormal);
tangentNormal.xy *= _BumpScale;
//转换成世界坐标法线
fixed3 worldNormal = normalize(float3(dot(i.T2W0.xyz, tangentNormal),dot(i.T2W1.xyz, tangentNormal),dot(i.T2W2.xyz, tangentNormal)));
//半罗伯特模型
float difLight= dot(lightDir,worldNormal)* 0.5+0.5;
difLight = smoothstep(0,1,difLight);
//离散化
float toon = floor(difLight * _Step)/_Step;
difLight = lerp(difLight, toon, _ToonEffect);
//光照模型
fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse.rgb * difLight;
fixed4 color = fixed4 (ambient + diffuse,1);
//宏开关控制
#if SNOW_ON
//积雪
if(dot(worldNormal,_SnowDir.xyz)>lerp(1,-1,_Snow))
{
color.rgb = _SnowColor.rgb;
}
#endif
return color;
}
ENDCG
}
}
}
- 宏控制代码
该脚本需要放在项目Editor文件夹中
using UnityEditor;
using UnityEngine;
public class Tools : MonoBehaviour
{
private static string SNOW_ON = "SNOW_ON";
[MenuItem("Tools/Shader/开启雪景宏")]
public static void OpenRimlight()
{
if (Shader.IsKeywordEnabled(SNOW_ON))
{
Shader.DisableKeyword(SNOW_ON);
}
else
{
Shader.EnableKeyword(SNOW_ON);
}
}
}
网友评论