代码暂未优化,多光源着色器:
Shader "Common/Skin/SSS_Wet"
{
Properties
{
_MainTex ("主纹理", 2D) = "white" {}
[HDR]_MakeUpCol("妆容颜色",Color)= (1,1,1,1)
_MakeUpTex ("妆容遮罩", 2D) = "balck" {}
_AOTex ("AO纹理", 2D) = "balck" {}
_AOpow("AO强度",Range(0,1))=1
_NormalTex("法线",2D)="white"{}
_NormalIntensity("法线强度",Range(0, 3))=1
_SSSLUT("SSSLUT",2D)="white"{}
_CurveFactor("曲线系数",Range(0,1))=1
_ScatteringTex("透光贴图",2D)="Black"{}
_ScatteringColor("sss颜色值", Color) = (1,1,1,1)
_Distortion("sss光线偏移", Float) = 1
_ScatteringPow("sss吸收强度", Float) = 1
_ScatteringScale("sss范围", Float) = 1
//---
//_InteriorColor("SSS吸收颜色",Color)=(1,1,1,1)
//_InteriorColorPower("SSS颜色强度",Float)=1
//_FrontSurfaceDistortion("正面SSS偏移",Float) = 1
//_BackSurfaceDistortion("背面SSS偏移",Float ) = 1
//_FrontSSSIntensity("正面SSS强度",Float) = 1
//_BackSSSIntensity("背面SSS强度",Float) = 1
[KeywordEnum(Delta,NoDelta)] Delta("细节(受环境影响)",Float) = 1
[KeywordEnum(GGX,Kelemen)] Spec("反射模式",Float) = 1
_F0("GGX/Kel系数(一般不动)",Range(0,1))=0.028
_SmoothTex ("粗糙纹理", 2D) = "white" {}
_KelemenLUT ("KelemenLUT", 2D) = "white" {}
_Smooth("粗糙度",Range(0,1))=0.5
_SpecularColor("反射颜色",color) = (1,1,1,1)
_SpecularScale("反射强度",Range(0,120))=10
_GlossTex("高光贴图",2D) = "white" {}
_GlossPow("高光",Range(0.01,90))=1
//_MoHu("模糊阴影",float)=1
//汗水..
_PointAmount("静态汗水数量",Float)=15
_PointCut("静态汗水剔除",Range(0,1))=1
_PointPositiveNormal("静态汗水高光位置",Range(0,1))=0.235
_PointNegativeNormal("静态汗水阴影位置",Range(0,1))=0.140
_RainDropAmount("动态汗水数量",Float)=5
_RainDropCut("动态汗水剔除",Range(0,1))=1
_RainDropPositiveNormal("动态汗水高光位置",Range(0,1))=0.235
_RainDropNegativeNormal("动态汗水阴影位置",Range(0,1))=0.140 //
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"}
LOD 100
Pass
{
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "UnityStandardBRDF.cginc"
#pragma multi_compile_fog
#include "UnityCG.cginc"
#pragma target 3.0
#pragma multi_compile DELTA_NODELTA DELTA_DELTA
#pragma multi_compile SPEC_GGX SPEC_KELEMEN
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "RainDrop.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 uv0 : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent: TANGENT;
};
struct v2f
{
float4 uv : TEXCOORD0;
float3 nDirWS:TEXCOORD1;
float3 worldPos : TEXCOORD2;
float3 tDirWS:TEXCOORD3;
float3 bDirWS:TEXCOORD4;
SHADOW_COORDS(5)
float3 frontDir:TEXCOORD6;
float3 clipFrontDir:TEXCOORD7;
UNITY_FOG_COORDS(1)
float4 pos : SV_POSITION;
};
sampler2D _MainTex;float4 _MainTex_ST;
sampler2D _SSSLUT;float4 _SSSLUT_ST;
float _CurveFactor;
sampler2D _NormalTex;float4 _NormalTex_ST;fixed _NormalIntensity;
fixed4 _SpecularColor;sampler2D _AOTex;fixed _GlossPow; sampler2D _GlossTex;
sampler2D _KelemenLUT;sampler2D _SmoothTex;fixed _Smooth;fixed _SpecularScale;
fixed _AOpow; fixed _F0;fixed _Distortion;sampler2D _ScatteringTex;
fixed _ScatteringPow;fixed _ScatteringScale;fixed4 _ScatteringColor;
fixed _FrontSurfaceDistortion;fixed _BackSurfaceDistortion;fixed _FrontSSSIntensity;
fixed _BackSSSIntensity; fixed4 _InteriorColor; fixed _InteriorColorPower;
//lut图方法
half3 BentNormalsDiffuseLighting(float3 normal, float3 L, float Curvature)
{
float NdotLBlurredUnclamped = dot(normal, L);
return tex2D(_SSSLUT, float2(NdotLBlurredUnclamped * 0.5 + 0.5, Curvature));
}
//细节Lut图方法
half3 deltaLighting(float3 normal, float3 L, float Curvature, float nl)
{
float NdotLBlurredUnclamped = dot(normal, L);
return tex2Dlod(_SSSLUT, float4((NdotLBlurredUnclamped * 0.5 + 0.5), Curvature, 0, 0));
}
//Lut反射方法
float fresnelReflectance( float3 H, float3 V, float F0 )
{
float base = 1.0 - dot( V, H );
float exponential = pow( base, 5.0 );
return exponential + F0 * ( 1.0 - exponential );
}
//sss耳朵方法
float SubSurfaceScattering(float3 viewDir,float3 lightDir,float3 normalDir,float frontSubSurfaceDistortion,float backSubSurfaceDistortion,float frontSSSIntensity,float backSSSIntensity) {
float3 frontLitDir = normalDir * frontSubSurfaceDistortion - lightDir;
float3 backLitDir = normalDir * backSubSurfaceDistortion + lightDir;
float frontSSS = saturate(dot(viewDir, -frontLitDir));
float backSSS = saturate(dot(viewDir, -backLitDir));
float result = saturate(frontSSS * frontSSSIntensity + backSSS*backSSSIntensity);
return result;
}
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv0, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv0, _NormalTex);
//Kelemen算法
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);
o.frontDir=normalize(mul(unity_ObjectToWorld,float4(0,0,1,0)).xyz);
o.clipFrontDir=normalize(mul(UNITY_MATRIX_MV,float4(0,0,1,0)).xyz);
//o.frontDir = normalize(mul(unity_ObjectToWorld,float4(0,0,1,0)).xyz);
UNITY_TRANSFER_FOG(o,o.vertex);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);
//汗水参数
RainDropData rain=RainDrop(i.uv,i.worldPos,TBN);
//-----
//float3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos.xyz));
#ifdef USING_DIRECTIONAL_LIGHT //平行光下可以直接获取世界空间下的光照方向
fixed3 lightDir = _WorldSpaceLightPos0.xyz;
#else //其他光源下_WorldSpaceLightPos0代表光源的世界坐标,与顶点的世界坐标的向量相减可得到世界空间下的光照方向
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
fixed4 col = tex2D(_MainTex, i.uv);
//汗水
col.rgb=(col.rgb+rain.rainColor)*rain.fullMask;
fixed AOTex = saturate(tex2D(_AOTex, i.uv));
fixed GlossTex = saturate(tex2D(_GlossTex, i.uv));
float3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos.xyz));
UNITY_APPLY_FOG(i.fogCoord, col);
//法线凹凸
float3 bump =UnpackNormal(tex2D(_NormalTex,i.uv.zw));
//汗水
bump=BlendNormals(bump,rain.normal);
//bump = TransfromTanToWorld(bump,tanToWorld);
float3 bump_Var = float3((bump.r*_NormalIntensity),(bump.g*_NormalIntensity),bump.b);
float3 worldNormal = normalize(mul(bump_Var,TBN));
float3 reflectDir = normalize(reflect(-lightDir,worldNormal));
float NdotL = saturate(dot(worldNormal, lightDir));
float NdotV = saturate(dot(worldNormal, viewDir));
float3 halfVector = normalize(lightDir + viewDir);
float NdotH = saturate(dot(worldNormal, halfVector));
float LdotH = saturate(dot(lightDir, halfVector));
float RdotV = saturate(dot(reflectDir,viewDir));
half3 ambient_contrib = ShadeSH9(float4(worldNormal, 1));//采样Unity环境贴图
col.rgb*=pow(1-AOTex,_AOpow);
#if DELTA_DELTA
//curvature-------
float deltaWorldNormal = length(fwidth(worldNormal));
float deltaWorldPos = length(fwidth(i.worldPos.xyz));
float curvature = (deltaWorldNormal / deltaWorldPos) * _CurveFactor;
//delta细节添加
float3 directDiffuse_Var = deltaLighting(worldNormal, lightDir, curvature, NdotL);
float3 indirectDiffuse = max(half3(0, 0, 0), col.rgb * 0.03 + ambient_contrib*0.25);
float3 directDiffuse = (directDiffuse_Var + indirectDiffuse)*col.rgb;
//漫射
#elif DELTA_NODELTA
float3 directDiffuse = BentNormalsDiffuseLighting(worldNormal,lightDir,_CurveFactor);
directDiffuse*=col.rgb;
#endif
//反射----------
float smoothness = tex2D(_SmoothTex, i.uv.xy).r * _Smooth;
float perceptualRoughness = 1 - smoothness;
float roughness = perceptualRoughness * perceptualRoughness;
#if SPEC_KELEMEN
float3 kelemen = tex2D(_KelemenLUT, float2(NdotH, smoothness));
float PH = pow(2.0 * kelemen, 10.0);
//fixed F0 = 0.028;
fixed F = fresnelReflectance(halfVector, viewDir, _F0);
half3 specularColor = max(PH * F / dot(halfVector, halfVector), 0);
//------
#elif SPEC_GGX
float alpha = roughness;
float G_L = NdotL + sqrt((NdotL - NdotL * alpha) * NdotL + alpha);
float G_V = NdotV + sqrt((NdotV - NdotV * alpha) * NdotV + alpha);
float G = G_L * G_V;
fixed F = fresnelReflectance(halfVector, viewDir, _F0);
float alpha2 = alpha * alpha;
float denominator = (NdotH * NdotH) * (alpha2 - 1) + 1;
float D = alpha2 / (UNITY_PI * denominator * denominator);
half3 specularColor = D * G * NdotL * F;
#endif
fixed3 specular = specularColor * FresnelTerm(_SpecularColor, LdotH) * _SpecularScale;
//高光+汗水
fixed3 GlossCol = max(0,pow(RdotV, _GlossPow)-rain.rainTrace) *_SpecularColor.rgb * GlossTex;
//无汗水 fixed3 GlossCol = pow(RdotV, _GlossPow)*_SpecularColor.rgb * GlossTex;
//SSS
float scattering = tex2D(_ScatteringTex, i.uv.xy).r;
float3 translightDir = lightDir + worldNormal * _Distortion;
float transDot = pow(saturate(dot(-translightDir, viewDir)) * scattering * scattering, _ScatteringPow) * _ScatteringScale;
float3 lightScattering = transDot * _ScatteringColor;
//SSS 耳朵
//float SSS = SubSurfaceScattering(viewDir, lightDir, worldNormal, _FrontSurfaceDistortion,_BackSurfaceDistortion,_FrontSSSIntensity,_BackSSSIntensity);
//float3 SSSCol = lerp(_InteriorColor, float3(1,1,1), saturate(pow(SSS, _InteriorColorPower))).rgb*SSS;
//SSSCol*=(1-scattering);
//float FdotL=saturate(dot(lightDir,i.frontDir));
//float CFdotF=abs(dot(float3(0,0,-1),i.clipFrontDir));
//SSSCol*=(1-FdotL)*pow(CFdotF,5);
//float3 disDir = -lightDir + worldNormal * _Distortion*1.75;
//fixed disCol = dot(-disDir, viewDir);
//计算环境光
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
/*#ifdef USING_DIRECTIONAL_LIGHT //平行光下不存在光照衰减,恒值为1
fixed atten = 1.0;
#else
#if defined (POINT) //点光源的光照衰减计算
//unity_WorldToLight内置矩阵,世界空间到光源空间变换矩阵。与顶点的世界坐标相乘可得到光源空间下的顶点坐标
float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
//利用Unity内置函数tex2D对Unity内置纹理_LightTexture0进行纹理采样计算光源衰减,获取其衰减纹理,
//再通过UNITY_ATTEN_CHANNEL得到衰减纹理中衰减值所在的分量,以得到最终的衰减值
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#elif defined (SPOT) //聚光灯的光照衰减计算
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
//(lightCoord.z > 0):聚光灯的深度值小于等于0时,则光照衰减为0
//_LightTextureB0:如果该光源使用了cookie,则衰减查找纹理则为_LightTextureB0
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
#endif
*/
//使用内置宏来计算光照衰减和阴影
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
//最终
fixed3 finacol = directDiffuse + specular*_LightColor0 + GlossCol + lightScattering ;
finacol*=_LightColor0 ;
finacol+=ambient;
finacol*=atten;
return fixed4(finacol,1);
}
ENDCG
}
Pass
{ Name "MakeUp"
Tags {"LightMode"="ForwardBase"}
Blend DstColor Zero
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#pragma target 3.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float4 uv0 : TEXCOORD0;
};
struct v2f
{
float4 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
UNITY_FOG_COORDS(1)
};
sampler2D _MakeUpTex;
float4 _MakeUpTex_ST;fixed4 _MakeUpCol;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv0.xy, _MakeUpTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MakeUpTex, i.uv);
fixed3 col02 = fixed3 (1,1,1)- col.rgb;
col.rgb*=_MakeUpCol;
col.rgb+=col02;
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
//多光源处理,只加光泽和光颜色,包含点光源的反射
Pass
{
Tags{"LightMode" = "ForwardAdd"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityStandardBRDF.cginc"
#pragma multi_compile_fwdadd
#include "UnityCG.cginc"
#pragma target 3.0
#pragma multi_compile DELTA_NODELTA DELTA_DELTA
#pragma multi_compile SPEC_GGX SPEC_KELEMEN
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "RainDrop.cginc"
//float _Gloss;
//float4 _Diffuse;
//float4 _Specular;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 uv0 : TEXCOORD0;
float4 tangent: TANGENT;
};
struct v2f {
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 worldPos : TEXCOORD1;
float3 nDirWS : TEXCOORD2;
float3 tDirWS:TEXCOORD3;
float3 bDirWS:TEXCOORD4;
float3 frontDir:TEXCOORD5;
};
sampler2D _MainTex;float4 _MainTex_ST;sampler2D _SmoothTex;fixed _Smooth;
sampler2D _NormalTex;float4 _NormalTex_ST;sampler2D _SSSLUT;float4 _SSSLUT_ST;
fixed _NormalIntensity;fixed _CurveFactor;sampler2D _KelemenLUT;fixed _F0;
fixed4 _SpecularColor;fixed _SpecularScale;sampler2D _GlossTex;fixed _GlossPow;
fixed _Distortion;sampler2D _ScatteringTex;fixed _ScatteringPow;fixed _ScatteringScale;
fixed4 _ScatteringColor;
//lut图方法
half3 BentNormalsDiffuseLighting(float3 normal, float3 L, float Curvature)
{
float NdotLBlurredUnclamped = dot(normal, L);
return tex2D(_SSSLUT, float2(NdotLBlurredUnclamped * 0.5 + 0.5, Curvature));
}
//细节Lut图方法
half3 deltaLighting(float3 normal, float3 L, float Curvature, float nl)
{
float NdotLBlurredUnclamped = dot(normal, L);
return tex2Dlod(_SSSLUT, float4((NdotLBlurredUnclamped * 0.5 + 0.5), Curvature, 0, 0));
}
//Lut反射方法
float fresnelReflectance( float3 H, float3 V, float F0 )
{
float base = 1.0 - dot( V, H );
float exponential = pow( base, 5.0 );
return exponential + F0 * ( 1.0 - exponential );
}
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.zw = TRANSFORM_TEX(v.uv0, _NormalTex);
o.uv.xy = TRANSFORM_TEX(v.uv0, _MainTex);
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);
return o;
}
fixed4 frag(v2f i) : SV_Target
{ float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);
//汗水参数
RainDropData rain=RainDrop(i.uv,i.worldPos,TBN);
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
float3 bump =UnpackNormal(tex2D(_NormalTex,i.uv.zw));
//汗水
bump=BlendNormals(bump,rain.normal);
float3 bump_Var = float3((bump.r*_NormalIntensity),(bump.g*_NormalIntensity),bump.b);
float3 worldNormal = normalize(mul(bump_Var,TBN));
fixed GlossTex = saturate(tex2D(_GlossTex, i.uv));
fixed3 nDirWS = normalize(i.nDirWS);
#ifdef USING_DIRECTIONAL_LIGHT //平行光下可以直接获取世界空间下的光照方向
fixed3 lightDir = _WorldSpaceLightPos0.xyz;
#else //其他光源下_WorldSpaceLightPos0代表光源的世界坐标,与顶点的世界坐标的向量相减可得到世界空间下的光照方向
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
#endif
//参数准备
fixed4 col = tex2D(_MainTex, i.uv);
//汗水
col.rgb=(col.rgb+rain.rainColor)*rain.fullMask;
float3 reflectDir = normalize(reflect(-lightDir,worldNormal));
float NdotL = saturate(dot(worldNormal, lightDir));
half3 ambient_contrib = ShadeSH9(float4(worldNormal, 1));//采样Unity环境贴图
float3 halfVector = normalize(lightDir + viewDir);
float NdotH = saturate(dot(worldNormal, halfVector));
float NdotV = saturate(dot(worldNormal, viewDir));
float LdotH = saturate(dot(lightDir, halfVector));
float RdotV = saturate(dot(reflectDir,viewDir));
//漫射光
#if DELTA_DELTA
float deltaWorldNormal = length(fwidth(worldNormal));
float deltaWorldPos = length(fwidth(i.worldPos.xyz));
float curvature = (deltaWorldNormal / deltaWorldPos) * _CurveFactor;
float3 directDiffuse_Var = deltaLighting(worldNormal, lightDir, curvature, NdotL);
float3 indirectDiffuse = max(half3(0, 0, 0), fixed4(1,1,1,1).rgb * 0.03 + ambient_contrib*0.25);
float3 directDiffuse = directDiffuse_Var + indirectDiffuse;
#elif DELTA_NODELTA
float3 directDiffuse = BentNormalsDiffuseLighting(worldNormal,lightDir,_CurveFactor);
#endif
//反射----------
float smoothness = tex2D(_SmoothTex, i.uv.xy).r * _Smooth;
float perceptualRoughness = 1 - smoothness;
float roughness = perceptualRoughness * perceptualRoughness;
#if SPEC_KELEMEN
float3 kelemen = tex2D(_KelemenLUT, float2(NdotH, smoothness));
float PH = pow(2.0 * kelemen, 10.0);
fixed F = fresnelReflectance(halfVector, viewDir, _F0);
half3 specularColor = max(PH * F / dot(halfVector, halfVector), 0);
#elif SPEC_GGX
float alpha = roughness;
float G_L = NdotL + sqrt((NdotL - NdotL * alpha) * NdotL + alpha);
float G_V = NdotV + sqrt((NdotV - NdotV * alpha) * NdotV + alpha);
float G = G_L * G_V;
fixed F = fresnelReflectance(halfVector, viewDir, _F0);
float alpha2 = alpha * alpha;
float denominator = (NdotH * NdotH) * (alpha2 - 1) + 1;
float D = alpha2 / (UNITY_PI * denominator * denominator);
half3 specularColor = D * G * NdotL * F;
#endif
fixed3 specular = specularColor * FresnelTerm(_SpecularColor, LdotH) * _SpecularScale;
//高光
//fixed3 GlossCol = pow(RdotV, _GlossPow) *_SpecularColor.rgb * GlossTex;
fixed3 GlossCol = max(0,pow(RdotV, _GlossPow)-rain.rainTrace) *_SpecularColor.rgb * GlossTex;
//SSS
float3 translightDir = lightDir + worldNormal * _Distortion;
float scattering = tex2D(_ScatteringTex, i.uv.xy).r;
float transDot = pow(saturate(dot(-translightDir, viewDir)) * scattering * scattering, _ScatteringPow) * _ScatteringScale;
float3 lightScattering = transDot * _ScatteringColor;
//漫反射光的计算公式
fixed3 diffuse = _LightColor0.rgb * col.rgb * directDiffuse;
//环境光的计算公式
//fixed3 halfDir = normalize(lightDir + viewDir);
//fixed3 specular = _LightColor0.rgb * fixed4(1,1,1,1).rgb * pow(max(0, dot(nDirWS, halfDir)), 90);
/*这段ifelse的代码可以直接使用unity内置宏UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
但是该结果表示光照衰减和该物体接收来自其他物体的阴影纹理的效果,阴影在下一章节有讲。
*/
/*
#ifdef USING_DIRECTIONAL_LIGHT //平行光下不存在光照衰减,恒值为1
fixed atten = 1.0;
#else
#if defined (POINT) //点光源的光照衰减计算
//unity_WorldToLight内置矩阵,世界空间到光源空间变换矩阵。与顶点的世界坐标相乘可得到光源空间下的顶点坐标
float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
//利用Unity内置函数tex2D对Unity内置纹理_LightTexture0进行纹理采样计算光源衰减,获取其衰减纹理,
//再通过UNITY_ATTEN_CHANNEL得到衰减纹理中衰减值所在的分量,以得到最终的衰减值
fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#elif defined (SPOT) //聚光灯的光照衰减计算
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
//(lightCoord.z > 0):聚光灯的深度值小于等于0时,则光照衰减为0
//_LightTextureB0:如果该光源使用了cookie,则衰减查找纹理则为_LightTextureB0
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
#endif
*/
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
//这里不再计算环境光,在上个Base Pass中已做计算
return fixed4((diffuse + specular + GlossCol + lightScattering)* atten, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
#ifndef RAIN_DROP
#define RAIN_DROP
float _PointAmount,_PointCut,_PointPositiveNormal,_PointNegativeNormal;
float _RainDropAmount,_RainDropCut,_RainDropPositiveNormal,_RainDropNegativeNormal;
float _UseNormal;
struct RainDropData
{
float3 normal;
fixed3 rainColor;
fixed fullMask;
fixed rainTrace;
};
float3 N13(float2 uv)
{
float p=uv.x*35.2+uv.y*2376.1;
float3 p3 = frac(float3(p,p,p) * float3(.1031,.11369,.13787));
p3 += dot(p3, p3.yzx + 19.19);
return frac(float3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
float3 BlendNormals(float3 n1,float3 n2)
{
n1.z=n1.z+1;
n2.xy=-n2.xy;
float NdotN=dot(n1,n2);
return n1*NdotN-n2*n1.z;
}
// XY:frac ZW:floor
float4 UVConfigure(float2 uv,float time,float2 scale,float amount)
{
uv=uv*scale;
uv.y+=time;
//根据U值给随机值将UV错开
float factor=frac(sin(floor(amount*uv.x)*12345.580078)*7658.759766);
uv.y+=factor;
uv*=amount;
float4 Out=0;
//floor:返回小于等于x的最大整数。
//进行分区
Out.zw=floor(uv);
//frac返回输入值的小数部分。
//x[0,1]---->[-0.5,0.5]
//将uv分块
Out.xy=frac(uv)-float2(0.5,0);
//Out.xy=frac(uv);
return Out;
}
float4 RainDropAndPointUV(float3 N,float2 fracUV,float time,float4 tillingOffset,float Cut,out float cut)
{
cut=Cut;
cut=floor(cut+N.y);
half2 offsetUV=0;
offsetUV.x=(N.x-0.5)*0.5;
float v=frac(N.y+time);
v=smoothstep(0,0.85,v)*smoothstep(1,0.85,v)-0.5;
offsetUV.y=v*0.5+0.5;
float2 uv=(fracUV-offsetUV)*tillingOffset.xy;
//float2 uv=fracUV*2;
return float4(offsetUV,uv);
}
float2 Mask(float2 uv,float3 scaleAndDir,float4 smoothRange,float2 cutAndBase)
{
//取负突出暗部,再和噪声相加获取渐变效果
float maskBase=length(uv*scaleAndDir.xy)*scaleAndDir.z+cutAndBase.y;
float2 mask=1;
//内圈 凹
mask.x=smoothstep(smoothRange.x,smoothRange.y,maskBase)*cutAndBase.x;
//外圈 凸
mask.y=smoothstep(smoothRange.z,smoothRange.w,maskBase)*cutAndBase.x;
return mask;
}
void TUV(float2 uv,float2 PosiNegaNormal,out float3 normal,out float3 causticNormal)
{
normal=0;
causticNormal=0;
normal.y=abs(uv.x)*abs(uv.x)+uv.y;
normal.x=abs(uv.y)*abs(uv.y)+uv.x;
causticNormal.xy=-normal.xy;
normal.z=PosiNegaNormal.x;
normal=normalize(normal);
causticNormal.z=PosiNegaNormal.y;
causticNormal=normalize(causticNormal);
}
float3 TransfromTanToWorld(float3 normal,float3x3 tanToworld)
{
float3 worldNormal;
worldNormal.x = dot(tanToworld[0], normal);
worldNormal.y = dot(tanToworld[1], normal);
worldNormal.z = dot(tanToworld[2], normal);
return normalize(worldNormal);
}
float RainTrace(float2 uv,float2 fracUV)
{
float lineWidth=abs(fracUV.x-uv.x);
float lineHeight=smoothstep(1,uv.y,fracUV.y);
float base=sqrt(lineHeight);
float widthMax=base*0.23;
float widthMin=base*0.15*base;
lineWidth=smoothstep(widthMax,widthMin,lineWidth);
float trace=smoothstep(-0.02,0.02,fracUV.y-uv.y)*lineHeight;
trace*=lineWidth;
return max(0,trace);
}
RainDropData MixStaticDynamic(float3 normal,float3 causticNormal,float2 mask,
float3 dropNormal,float3 dropCausticNormal,float2 dropMask,
float3 viewDir,float3x3 tanToWorld)
{
RainDropData rain=(RainDropData)0;
float3 lightDir=float3(-0.3,1,-0.3);
lightDir=normalize(lightDir);
float3 halfDir=normalize(viewDir+lightDir);
float3 yDir=float3(0,1,0);
fixed downMask=mask.x+dropMask.x;
fixed riseMask=mask.y+dropMask.y;
float3 riseNormal=lerp(normal,dropNormal,dropMask.y);
//float3 useNormal=BlendNormals(riseNormal,float3(0,0,1));
riseNormal=TransfromTanToWorld(riseNormal,tanToWorld);
float RdotV=smoothstep(0.9,1.2,dot(riseNormal,halfDir));
RdotV*=RdotV;
float3 downNormal=lerp(causticNormal,dropCausticNormal,dropMask.x);
float3 useNormal=BlendNormals(downNormal,float3(0,0,1));
downNormal=TransfromTanToWorld(downNormal,tanToWorld);
float DdotC=smoothstep(0.5,1.5,dot(downNormal,lightDir));
DdotC*=DdotC;
float RdotZ=smoothstep(-1.3,0.3,dot(yDir,riseNormal));
fixed fullMask=saturate(lerp(1,RdotZ,riseMask)+downMask);
//fixed fullMask=lerp(1,RdotZ,riseMask);
fixed3 rainDiffuseColor=RdotV*downMask*10;
fixed3 rainCausticColor=DdotC*downMask*4;
rain.normal=useNormal;
rain.rainColor=rainDiffuseColor+rainCausticColor;
rain.fullMask=fullMask;
return rain;
}
RainDropData RainDrop(float2 uv,float3 worldPos,float3x3 tanToWorld)
{
RainDropData rainData=(RainDropData)0;
float t=_Time.y;
float cut;
//静态水滴-------------------
float4 configure=UVConfigure(uv,0,1,_PointAmount);
float3 N=N13(configure.zw);
float4 rain=RainDropAndPointUV(N,configure.xy,0,float4(2,2,0,0),_PointCut,cut);
//噪声值慢慢变大,由frac再变回0
float fade=smoothstep(0.2,1,1-frac(t*0.05+N.z));
float2 mask=Mask(rain.zw,float3(3.54,2.1,-1),float4(0.3,0.44,0.1,0.45),float2(cut,fade));
//float2 mask=Mask(rain.zw,float3(3.54,2.1,-1),float4(0.1,0.44,0.1,0.45),float2(cut,fade));
//法线
float3 normal,causticNormal;
float2 factor=float2(_PointPositiveNormal,_PointNegativeNormal);
TUV(rain.zw,factor,normal,causticNormal);
float3 up=float3(0,0,1);
normal=lerp(up,normal,mask.y);
causticNormal=lerp(up,causticNormal,mask.x);
//--------------------------
float4 configureDrop=UVConfigure(uv,0.02*t,float2(5,1), _RainDropAmount);
N=N13(configureDrop.zw);
float4 rainDrop=RainDropAndPointUV(N,configureDrop.xy,t*0.05,float4(1,5,0,0),_RainDropCut,cut);
float2 rainDropMask=Mask(rainDrop.zw,float3(2.9,1.8,1),float4(0.68,0.44,0.8,0.57),float2(cut,0));
//float2 rainDropMask=Mask(rainDrop.zw,float3(2.9,1.8,1),float4(0.75,0.57,0.8,0.57),float2(cut,0));
float rainDropTrace=RainTrace(rainDrop.xy,configureDrop.xy)*cut+mask.x+rainDropMask.x;
float3 dropNormal,dropCausticNormal;
factor=float2(_RainDropPositiveNormal,_RainDropNegativeNormal);
TUV(rainDrop.zw,factor,dropNormal,dropCausticNormal);
dropNormal*=rainDropMask.y;
dropCausticNormal*=rainDropMask.x;
float3 viewDir=normalize(UnityWorldSpaceViewDir(worldPos));
rainData=MixStaticDynamic(normal,causticNormal,mask,dropNormal,dropCausticNormal,rainDropMask,viewDir,tanToWorld);
rainData.rainTrace=rainDropTrace;
return rainData;
}
#endif