原神卡通渲染shader
Shader "Unlit/Yuanshen"
{
Properties
{
_BaseMap("BaseMap", 2D) = "white" {}
_LightMap("Light Map",2D) = "white" {}
_RampTex("Ramp Tex",2D) = "white" {}
_MetalMap("Metal Map",2D) = "white"{}
_SDF("SDF",2D) = "white"{}
[Header(BaseColor)]
[Toggle]_Day("Day",int) = 1
//去控制横向采样的长度与Ramp偏移
_RampShadowRange("RampShadowRange",Range(0,1)) = 0
//_RampMapRangStart("RampMapRangStart",float) = 0
//_RampMapFields("RampMapFields",float) = 0
_ShadowRampLerp("ShadowRampLerp",Range(0,1)) = 0
//控制明暗的分布
_RampAOLerp("RampAOLerp",Range(0,1)) = 0
_DarkIntensity("暗部亮度 ",Range(0,5)) = 0
_DarkShadowMultColor("暗部颜色",Color) = (1,1,1,1)
_ShadowMultColor("亮部颜色",Color) = (1,1,1,1)
_BrightIntensity("亮部强度",Range(0,5)) = 0
_CharacterIntensity("整体亮度",Range(0,5)) = 0
_RampIntensity("Ramp图亮度",Range(0,5)) = 0
[Header(SpecularColor)]
[Toggle]_EnableHair("是否为头发",int) = 0
_SpecularPow("高光幂次数",float) = 5
_SpecularIntensity("高光强度",float) = 1
_SpecularExp("Specular Exp",float) = 1
_StepSpecularWidth("第一层高光范围",Range(0,1)) = 1
_StepSpecularWidth2("第二层高光范围",Range(0,1)) = 1
_StepSpecularWidth3("第三层高光范围",Range(0,1)) = 1
_StepSpecularWidth4("第四层高光范围(头发)",Range(0,1)) = 1
_StepSpecularIntensity("第一层高光强度",float) = 1
_StepSpecularIntensity2("第二层高光强度",float) = 1
_StepSpecularIntensity3("第三层高光强度",float) = 1
_StepSpecularIntensity4("第四层高光强度(头发)",float) = 1
_MetalMapV("MetalMapV",Range(0,1)) = 1
_MetalMapIntensity("MetalMapIntensity",float) = 1
_HairSpecularRange("头发高光范围",Range(0,1)) = 1
_HairSpecularViewRange("高光视角范围",Range(0,1)) = 1
_HairSpecularIntensity("头发高光强度",float) = 1
_HairSpecularColor("高光颜色",color) = (1,1,1,1)
[Header(RimLight)]
_Lightcolor("边缘光颜色",Color) = (1,1,1,1)
_RimOffect ("偏移量(xy)",vector) = (1.25,0.2,0,0)
_Threshold("Threshold",Range(-1,1)) = 0.2
_FresnelPow("菲涅尔强度",Range(0,10)) = 4
_RimIntensity("边缘光强度",Range(0,10)) =1
[Header(Faceshadow)]
[Toggle]_FaceShadow("是否启用脸部阴影",int) = 0
_ShadowColor("ShadowColor",Color) = (0,0,0,0)
[Header(OutLine)]
_Outline ("Outline", Range(0, 1)) = 0.003
_OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)
}
SubShader
{
Tags { "Queue" = "Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True" }
Pass
{
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#pragma shader_feature _ _DAY_ON
#pragma shader_feature _ _ENABLEHAIR_ON _FACESHADOW_ON
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normalWS : TEXCOORD1;
float4 worldPos : TEXCOORD2;
float3 normalVS : TEXCOORD5;
float2 ScreenPos01 : TEXCOORD3;
float srcposW : TEXCOORD4;
};
float4 _BaseMap_ST;
half _RampShadowRange;
half _Day;
half _ShadowRampLerp;
half _RampAOLerp;
half _DarkIntensity;
half4 _DarkShadowMultColor;
half _BrightIntensity;
half4 _ShadowMultColor;
half _CharacterIntensity;
half _RampIntensity;
half _SpecularPow;
half _SpecularExp;
half _SpecularIntensity;
half _StepSpecularWidth;
half _StepSpecularWidth2;
half _StepSpecularWidth3;
half _StepSpecularWidth4;
half _StepSpecularIntensity;
half _StepSpecularIntensity2;
half _StepSpecularIntensity3;
half _StepSpecularIntensity4;
half _MetalMapV;
half _MetalMapIntensity;
half _HairSpecularRange;
half _HairSpecularViewRange;
half _HairSpecularIntensity;
half4 _HairSpecularColor;
half4 _Lightcolor;
half4 _RimOffect;
half _Threshold;
half _FresnelPow;
half _RimIntensity;
fixed4 _ShadowColor;
sampler2D _CameraDepthTexture;
sampler2D _BaseMap;
sampler2D _LightMap;
sampler2D _RampTex;
sampler2D _MetalMap;
sampler2D _SDF;
//float4 _BaseMap_ST;
float4 _LightMap_ST;
float4 _RampTex_ST;
float4 _MetalMap_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
o.uv = v.uv;
o.normalWS = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
o.srcposW = o.vertex.w;
o.normalVS = mul((float3x3)UNITY_MATRIX_V , o.normalWS);
o.ScreenPos01 = float2(v.vertex.x / _ScreenParams.x , v.vertex.y / _ScreenParams.y);
return o;
}
half4 frag (v2f i) : SV_Target
{
fixed4 baseMap = tex2D(_BaseMap, i.uv);
float4 LightColor = float4( _LightColor0.rgb,1); //获取主光源颜色
half3 N = normalize(i.normalWS);
half3 L = normalize(_WorldSpaceLightPos0.xyz);
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
half3 V = normalize(viewDir);
half3 H = normalize(V + L);
half3 ShadowColor = baseMap.rgb * _ShadowMultColor.rgb; //亮部颜色
half3 DarkShadowColor = baseMap.rgb * _DarkShadowMultColor.rgb; //暗部颜色
//Lightmap
half4 lightmap = tex2D(_LightMap, i.uv);
half ao = lightmap.g;
//Ramp
half lambert = saturate(dot(N, L));
half halfLambert = lambert * 0.5 + 0.5;
float rampvmove = 0.0; //如果是夜晚,采样ramp图下面
float rampvalue = halfLambert * lerp(0.5, 1.0, ao) * (1.0 / _RampShadowRange - 0.0003);
//ramp图前5行为暖色调阴影,后5行为冷色调阴影,对应着夜晚与⽩天。
#if _DAY_ON
rampvmove += 0.5; //如果是白天,采样ramp图上面
#endif
half3 ShadowRamp1 = tex2D(_RampTex, float2(rampvalue, 0.4 + rampvmove)).rgb;
half3 ShadowRamp2 = tex2D(_RampTex, float2(rampvalue, 0.3 + rampvmove)).rgb;
half3 ShadowRamp3 = tex2D(_RampTex, float2(rampvalue, 0.2 + rampvmove)).rgb;
half3 ShadowRamp4 = tex2D(_RampTex, float2(rampvalue, 0.1 + rampvmove)).rgb;
half3 ShadowRamp5 = tex2D(_RampTex, float2(rampvalue, 0.0 + rampvmove)).rgb;
//将所有的Ramp加起来
half3 skinRamp = step(abs(lightmap.a - 1), 0.05) * ShadowRamp1; //皮肤ramp
float3 tightsRamp = step(abs(lightmap.a - 0.7), 0.05) * ShadowRamp2; //皮肤与衣服的交界
float3 softCommonRamp = step(abs(lightmap.a - 0.5), 0.05 ) * ShadowRamp3; //衣服ramp
half3 hardSilkRamp = step(abs(lightmap.a - 0.3), 0.05) * ShadowRamp4; //衣服边缘
half3 metalRamp = step(abs(lightmap.a - 0), 0.05) * ShadowRamp5;
// 组合5个Ramp,得到最终的Ramp阴影,并根据rampValue与BaseColor结合。
half3 finalRamp = skinRamp + tightsRamp + metalRamp + hardSilkRamp + softCommonRamp;
//return half4(finalRamp,1);
//因为和阴影同时 出现
rampvalue = step(_RampShadowRange, halfLambert) ;
half3 RampShadowColor = lerp(finalRamp * baseMap.rgb, baseMap.rgb, rampvalue);
//return half4(RampShadowColor,1);
//用_ShadowRampLerp控制lerp的强度,随之控制AO区域的明暗程度
float3 BaseMapShadowed = lerp(baseMap.rgb * finalRamp , baseMap.rgb, ao);
BaseMapShadowed = lerp(baseMap.rgb, BaseMapShadowed, _ShadowRampLerp);
float IsBrightSide = ao * step(_RampShadowRange, halfLambert); //辨别是否为亮部
float3 Diffuse = lerp(lerp(BaseMapShadowed, baseMap.rgb * finalRamp, _RampAOLerp)
* _DarkIntensity * DarkShadowColor, _BrightIntensity * BaseMapShadowed * ShadowColor,
IsBrightSide * _RampIntensity ) * _CharacterIntensity * LightColor.rgb;
//return half4(Diffuse,1);
//高光部分
float4 MetalMap = tex2D(_MetalMap, mul((float3x3)UNITY_MATRIX_V, N).xy).r;
MetalMap = saturate(MetalMap);
MetalMap = step(_MetalMapV, MetalMap) * _MetalMapIntensity;
float3 Specular = 0;
float3 StepSpecular = 0;
float3 StepSpecular2 = 0;
float LinearMask = pow(lightmap.r, 1 / 2.2); //图⽚格式全部去掉勾选SRGB ⾼光类型Layer
float SpecularIntensityMask = pow(saturate(dot(N, V)), _SpecularPow) * _SpecularIntensity;
float SpecularLayer = lightmap.r * 255; //高光类型,不同的⾼光层 LightMap.b ⽤途不⼀样
float StepSpecularMask = step(200, pow(SpecularIntensityMask, 1 / 2.2) * 255); //高光强度遮罩,加伽马校正
if (SpecularLayer > 0 && SpecularLayer < 50) //丝袜与包包
{
//step x<=y返回1,否则返回0
StepSpecular = step(1 - _StepSpecularWidth, saturate(dot(N, V))) * _StepSpecularIntensity; //可做修改* SpecularIntensityMask
StepSpecular *= baseMap;
}
// 裁边⾼光 (⾼光在暗部消失)
if (SpecularLayer > 50 && SpecularLayer < 150) //布料边缘高光
{
StepSpecular = step(1 - _StepSpecularWidth2, saturate(dot(N, V))) * 1 * _StepSpecularIntensity2;//* SpecularIntensityMask
StepSpecular *= baseMap;
}
if (SpecularLayer > 150 && SpecularLayer < 250)//头发高光
{
#if _ENABLEHAIR_ON //如果是头发 ,取代高光,如果不是保持
StepSpecular = step(1 - _StepSpecularWidth3, saturate(dot(N, V))) * _StepSpecularIntensity3;
//StepSpecular = lerp(StepSpecular, 0, SpecularIntensityMask); //反向失去头发高光控制
StepSpecular2 = step(1 - _StepSpecularWidth4 * 5, saturate(dot(N, V))) * SpecularIntensityMask * _StepSpecularIntensity4;
StepSpecular2 *= baseMap;
StepSpecular *= baseMap;
#else
StepSpecular = step(1 - _StepSpecularWidth3, saturate(dot(N, V))) * _StepSpecularIntensity3;
StepSpecular *= baseMap;
#endif
}
if (SpecularLayer >= 250 && SpecularLayer < 260) //金属高光
{
Specular = pow(saturate(dot(N, H)), 1 * _SpecularExp) * SpecularIntensityMask * _SpecularIntensity;
Specular = max(0, Specular);
Specular += MetalMap;
Specular *= baseMap;
}
float SpecularRange = step(1 - _HairSpecularRange, saturate(dot(N, H)));
float ViewRange = step(1 - _HairSpecularViewRange, saturate(dot(N, V)));
float3 HairSpecular = 0;
HairSpecular = SpecularIntensityMask * _HairSpecularIntensity * SpecularRange * ViewRange;
HairSpecular = max(0, HairSpecular);
HairSpecular *= baseMap * LightColor.rgb;
HairSpecular *= _HairSpecularColor.rgb;
//return half4(HairSpecular,1);
//高光融合
Specular = lerp(StepSpecular, Specular, LinearMask); // //⾼光类型Layer 截断分布
Specular = lerp(0, Specular, LinearMask);
Specular = lerp(0, Specular, rampvalue); //亮暗分布rampValue 加上AO暗部影响
Specular += HairSpecular;
//float3 FinalColor = Specular + RampShadowColor; //Diffuse + Specular;
float3 FinalColor = Specular + Diffuse;
//边缘光
float fresnel = pow(1 - saturate(dot(N,V)),_FresnelPow);
float2 ScreenPosOffset = i.ScreenPos01 + i.normalVS.xy * _RimOffect.xy;
//float2 ScreenPosOffset = i.ScreenPos01 + i.normalVS.xy * float2(_RimOffect.xy / i.srcposW) / _ScreenParams.x ;
float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, i.ScreenPos01));
float depth01 = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, ScreenPosOffset));//偏移后的深度
float linearDepth = Linear01Depth(depth);
float linear01Depth = Linear01Depth(depth01);
float findepth = linear01Depth - linearDepth;
//return fresnel;
float rim = step(_Threshold,findepth);
rim = lerp(fresnel,rim,_Threshold);
//fixed4 col = fixed4(_Lightcolor.rgb * rim ,1);
//return rim;
FinalColor += rim *_Lightcolor.rgb *1.2 * _RimIntensity ;
//脸部阴影
half3 faceshadow = 0;
#if _FACESHADOW_ON
half3 LightDir = normalize(_WorldSpaceLightPos0.xyz);
float shadow = tex2D(_SDF, i.uv);//采样右脸阴影
float shadow01 = tex2D(_SDF, float2(-i.uv.x,i.uv.y));//采样左脸阴影
float3 FrontDir = normalize(UnityObjectToWorldDir(float3(0.0,0.0,1.0)));//拿到模型的向前方向z
float3 rightDir = normalize(UnityObjectToWorldDir(float3(1.0,0.0,0.0)));//拿到模型的向右方向x
float HalfLambert = dot(LightDir.xz,FrontDir.xz)* 0.5 + 0.5;
float Lambert = dot(LightDir.xz,rightDir.xz);
float Faceshadow = lerp(shadow,shadow01,step(Lambert,0));//判断该采样哪边的阴影
float face = HalfLambert>Faceshadow?1.0:0.0;
//return face;
faceshadow = lerp(_ShadowColor.rgb * FinalColor*1.2,FinalColor,face);
return half4(faceshadow,1);
#endif
return half4(FinalColor, 1);
}
ENDCG
}
Pass
{
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float _Outline;
fixed4 _OutlineColor;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert (a2v v)
{
v2f o;
float4 pos = mul(UNITY_MATRIX_MV, v.vertex);
float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
normal.z = -0.5;
pos = pos + float4(normalize(normal), 0) * _Outline;
o.pos = mul(UNITY_MATRIX_P, pos);
return o;
}
float4 frag(v2f i) : SV_Target
{
return float4(_OutlineColor.rgb, 1);
}
ENDCG
}
}
Fallback "Diffuse"
}