Files
AIC-Project/Client/Assets/Game/shader/SGame/Base/Lighting_Base.hlsl
T

367 lines
15 KiB
HLSL

#ifndef LIGHTING_BASE
#define LIGHTING_BASE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "ExpHeightFog_Base.hlsl"
#include "./CustomShadowMap_Base.hlsl"
CBUFFER_START(UnityPerMaterial_SCENE)
//线性雾
half4 _SG_FogHeightVector, _SG_FogHeightColor, _SG_FogRangeVector, _SG_FogColor;
half _SG_FogDensity;
//覆盖色
half4 _SG_CoverageColor; half _SG_CoverageLevel; half _SG_CoverageAmt; half _SG_CoverageFactor;
//环境光
half3 _SG_AmbientColor; half _SG_AmbientStrength; half3 _SG_ShadowColor;
//场景光
half _SG_DarkStrength;
//场景潮湿
half _SG_WetBumpHeightScale; half3 _SG_WetColor; half3 _SG_WetSpecularColor; half _SG_WetSpecularStrength; half _SG_WetSmoothness;
half _SG_WetFactor; half _SG_WetRippleSpeed; half4 _SG_WetBumpTilingOffset1; half4 _SG_WetBumpTilingOffset2;
half4 _SG_WetRippleTex_ST; half _SG_WetRippleStrength; half4 _SG_WetRippleTiling; half _SG_WetRippleBumpScale;
half3 _SG_ThunderDirection; half _SG_ThunderStrength; half3 _SG_ThunderColor;
CBUFFER_END
TEXTURE2D(_SG_WetRippleTex); SAMPLER(sampler_SG_WetRippleTex);
TEXTURE2D(_SG_WetBumpMap1); SAMPLER(sampler_SG_WetBumpMap1);
TEXTURE2D(_SG_WetBumpMap2); SAMPLER(sampler_SG_WetBumpMap2);
inline half SGamePow(half x, half n)
{
n = n * 1.4427f + 1.4427f; // 1.4427f --> 1/ln(2)
return exp2(x * n - n);
}
inline half3 RotationY(half3 pointP, half angle)
{
half radY = radians(angle);
half sinY = sin(radY);
half cosY = cos(radY);
return half3(pointP.x * cosY - pointP.z * sinY,
pointP.y,
pointP.x * sinY + pointP.z * cosY);
}
real ApplyMicroShadow(real ao, real3 N, real3 L, real shadow)
{
#if defined(_MICRO_SHADOW)
real aperture = 2.0 * ao * ao;
real microShadow = saturate(abs(dot(N, L)) + aperture - 1.0);
return shadow * microShadow;
#else
return shadow;
#endif
}
////APPLY_SCENE_EFFECT//////////////////////////////////////////////////////////////////////////////////////
half3 ApplyFog(half3 mainColor, half3 worldPos, half fogDensity)
{
half heightFade = 1 - saturate((worldPos.y - (_WorldSpaceCameraPos.y - _SG_FogHeightVector.x)) * _SG_FogHeightVector.y);
heightFade *= heightFade;
half3 finalColor = lerp(mainColor, _SG_FogHeightColor.rgb, heightFade * fogDensity);
half dist = length(_WorldSpaceCameraPos.xyz - worldPos.xyz);
half distFade = saturate((dist - _SG_FogRangeVector.x) * _SG_FogRangeVector.y);
finalColor = lerp(finalColor, _SG_FogColor.rgb, distFade * fogDensity);
return finalColor;
}
half3 ApplyFog_CustomOffset(half3 mainColor, half3 worldPos, half fogDensity, half offset)
{
half heightFade = 1 - saturate((worldPos.y + offset - (_WorldSpaceCameraPos.y - _SG_FogHeightVector.x)) * _SG_FogHeightVector.y);
heightFade *= heightFade;
half3 finalColor = lerp(mainColor, _SG_FogHeightColor.rgb, heightFade * fogDensity);
half dist = length(_WorldSpaceCameraPos.xyz - worldPos.xyz);
half distFade = saturate((dist - _SG_FogRangeVector.x) * _SG_FogRangeVector.y);
finalColor = lerp(finalColor, _SG_FogColor.rgb, distFade * fogDensity);
return finalColor;
}
half3 ApplyDark(half3 mainColor)
{
#if defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
return lerp(mainColor, half3(0, 0, 0), _SG_DarkStrength);
#else
return mainColor;
#endif
}
half3 ApplyCoverageColor (half3 mainColor, half worldNormalY, half offset)
{
return lerp(mainColor.rgb, _SG_CoverageColor.rgb, saturate(pow(worldNormalY, _SG_CoverageLevel * offset) * _SG_CoverageAmt));
}
half3 RgbToHsv_SGame(half3 c)
{
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
half d = q.x - min(q.w, q.y);
half e = 1.0e-4;
return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
half3 HsvToRgb_SGame(half3 c)
{
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
half3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, saturate(p - K.xxx), c.y);
}
half3 FixedSHEvalLinearL0L1(half4 normal)
{
half3 x;
half4 fixedSHAr = half4(0.058, 0.25, 0.57, 0.34);
half4 fixedSHAg = half4(0.046, 0.29, 0.55, 0.37);
half4 fixedSHAb = half4(0.028, 0.33, 0.47, 0.37);
x.r = dot(fixedSHAr,normal);
x.g = dot(fixedSHAg,normal);
x.b = dot(fixedSHAb,normal);
return x;
}
half3 FixedSHEvalLinearL2 (half4 normal)
{
half3 x1, x2;
half4 vB = normal.xyzz * normal.yzzx;
half4 fixedSHBr = half4(0.058, 0.31, 0.5, 0.12);
half4 fixedSHBg = half4(0.05, 0.29, 0.46, 0.11);
half4 fixedSHBb = half4(0.038, 0.24, 0.36, 0.11);
half4 fixedSHC = half4(0.0047, 0.011, 0.013, 1);
x1.r = dot(fixedSHBr,vB);
x1.g = dot(fixedSHBg,vB);
x1.b = dot(fixedSHBb,vB);
half vC = normal.x*normal.x - normal.y*normal.y;
x2 = fixedSHC.rgb * vC;
return x1 + x2;
}
half3 FixedShadeSH9 (half4 normal)
{
half3 res = FixedSHEvalLinearL0L1 (normal);
res += FixedSHEvalLinearL2 (normal);
return res;
}
inline half3 fresnel(half3 F0, half NdotV, half roughness, half factor)
{
return F0 + (max(1.0 - roughness, F0) - F0) * pow(1 - NdotV, factor);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////APPLY_SCENE_WET/////////////////////////////////////////////////////////////////////////////////////////
inline half2 ComputeRipple(half2 UV, half currentTime, half weight)
{
half4 ripple = SAMPLE_TEXTURE2D(_SG_WetRippleTex, sampler_SG_WetRippleTex, UV);
ripple.yz = ripple.yz * 2 - 1;
half dropFrac = frac(ripple.w + currentTime); // Apply time shift
half timeFrac = dropFrac - 1.0f + ripple.x;
half dropFactor = saturate(0.2f + weight * 0.8f - dropFrac);
half finalFactor = dropFactor * ripple.x * sin(clamp(timeFrac * 9.0f, 0.0f, 3.0f) * 3.141592653589793);
return ripple.yz * finalFactor;
}
// Add Water Ripples to Waterflow
inline half3 AddWetRipples(half3 worldPos, half3 worldNormal)
{
half weight = saturate(_SG_WetRippleStrength * 4);
half animSpeed = _Time.y * _SG_WetRippleSpeed;
half2 ripple = ComputeRipple(half2(worldPos.xz * _SG_WetRippleTiling), animSpeed, weight);
half3 rippleNormal = half3( weight * ripple.xy, 1) * _SG_WetRippleBumpScale;
return lerp( half3(0,0,1), rippleNormal, _SG_WetFactor * (worldNormal.y > 0.7));
}
half2 UnityFlipbook(half2 UV, half Width, half Height, half Tile)
{
Tile = Tile % (Width*Height);
half2 tileCount = half2(1.0, 1.0) / half2(Width, Height);
half tileY = max(Height - (floor(Tile * tileCount.x) + 1), 0);
half tileX = max(Tile - Width * floor(Tile * tileCount.x), 0);
return (UV + half2(tileX, tileY)) * tileCount;
}
inline half3 AddWetSheetRipples(half3 worldPos, half3 worldNormal)
{
half2 uv = worldPos.xz * _SG_WetRippleTiling;
half animSpeed = round(_Time.y * _SG_WetRippleSpeed);
half2 outUV = UnityFlipbook(uv, 4, 4, animSpeed);
half3 rippleNormal = SAMPLE_TEXTURE2D(_SG_WetRippleTex, sampler_SG_WetRippleTex, outUV) * 2 - 1;
return lerp( half3(0,0,1), rippleNormal * _SG_WetRippleBumpScale, _SG_WetFactor * worldNormal.y);
}
half3 SGameWetBump(half3 worldPos, half3 worldNormal)
{
half2 flowUV = half2(worldPos.x, worldPos.z);
half3 flowBump1 = SAMPLE_TEXTURE2D(_SG_WetBumpMap1, sampler_SG_WetBumpMap1, flowUV * _SG_WetBumpTilingOffset1.xy + _SG_WetBumpTilingOffset1.zw * _Time.y);
half3 flowBump2 = SAMPLE_TEXTURE2D(_SG_WetBumpMap2, sampler_SG_WetBumpMap2, flowUV * _SG_WetBumpTilingOffset2.xy + _SG_WetBumpTilingOffset2.zw * _Time.y);
half3 flowBump = flowBump1 - flowBump2;
half3 bumpNormal = lerp(half3(0,0,1), flowBump, _SG_WetFactor);
bumpNormal *= _SG_WetBumpHeightScale;
return bumpNormal;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
////VERTEX_ANIMATION////////////////////////////////////////////////////////////////////////////////////////
inline void FastSinCos(half4 val, out half4 s, out half4 c)
{
val = val * 6.408849 - 3.1415927;
half4 r5 = val * val;
half4 r6 = r5 * r5;
half4 r7 = r6 * r5;
half4 r8 = r6 * r5;
half4 r1 = r5 * val;
half4 r2 = r1 * r5;
half4 r3 = r2 * r5;
half4 sin7 = { 1, -0.16161616, 0.0083333, -0.00019841 };
half4 cos8 = { -0.5, 0.041666666, -0.0013888889, 0.000024801587 };
s = val + r1 * sin7.y + r2 * sin7.z + r3 * sin7.w;
c = 1 + r5 * cos8.x + r6 * cos8.y + r7 * cos8.z + r8 * cos8.w;
}
inline half4 ApplyFastWind(half4 vertex, half texCoordY, half wdSpeed = 0, half windBlend = 0)
{
half speed = wdSpeed;
half4 _waveXmove = half4 (0.024, 0.04, -0.12, 0.096);
half4 _waveZmove = half4 (0.006, .02, -0.02, 0.1);
const half4 waveSpeed = half4 (1.2, 2, 1.6, 4.8);
half4 waves;
waves = vertex.x * windBlend;
waves += vertex.z * windBlend;
waves += _Time.x * (1 - 0.4) * waveSpeed * speed;
half4 s, c;
waves = frac(waves);
FastSinCos(waves, s, c);
half waveAmount = texCoordY * (1 + 0.4);
s *= waveAmount;
s *= normalize(waveSpeed);
s = s * s;
half fade = dot(s, 1.3);
s = s * s;
half3 waveMove = half3 (0, 0, 0);
waveMove.x = dot(s, _waveXmove);
waveMove.z = dot(s, _waveZmove);
vertex.xz -= waveMove.xz;
return vertex;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////LIGHTING_MODES/////////////////////////////////////////////////////////////////////////////////////////
inline half3 GetAmbientColor(half3 mainColor, half3 shLight)
{
#ifdef LIGHTMAP_ON
half3 ambient = mainColor * shLight;
#else
half3 ambient = mainColor * (UNITY_LIGHTMODEL_AMBIENT.xyz + shLight);
#endif
ambient *= _SG_AmbientColor;
ambient *= _SG_AmbientStrength;
return ambient;
}
inline half3 GetAmbientColor_Custom(half3 mainColor, half3 shLight)
{
half3 ambient = lerp(mainColor, mainColor * UNITY_LIGHTMODEL_AMBIENT.xyz, shLight);
ambient *= _SG_AmbientColor;
ambient *= _SG_AmbientStrength;
return ambient;
}
inline half3 BlinnPhoneLighting(half3 mainColor, half3 worldPos, half3 worldNormal, half3 worldViewDir, half3 specularColor, half smoothness, half lightAtten,
half lightClamp = 20, half dotResLerp = 0, half3 customLightDir = half3(0, 0, 0), half useCustomDir = 0)
{
#if defined(SGAME_WET) && defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
mainColor = lerp(mainColor, mainColor * _SG_WetColor, _SG_WetFactor);
specularColor = lerp(specularColor, _SG_WetSpecularColor * _SG_WetSpecularStrength, _SG_WetFactor);
smoothness = lerp(lerp(smoothness, _SG_WetSmoothness, _SG_WetFactor), smoothness, smoothness > _SG_WetSmoothness);
#endif
//Diffuse
Light mainLight = GetMainLight();
half3 worldLightDir = normalize(mainLight.direction) * (1 - useCustomDir) + useCustomDir * customLightDir;
half H = normalize(worldViewDir + worldLightDir);
half NDotL = max(0, saturate(dot(worldNormal, worldLightDir)));
half ndotH = max(0, dot(worldNormal, H));
half dotLerp = lerp(NDotL, ndotH, dotResLerp);
half3 lightColor = lerp(_SG_ShadowColor, clamp(mainLight.color.rgb, 0, lightClamp), lightAtten * dotLerp);
specularColor = lerp(_SG_ShadowColor, clamp(mainLight.color.rgb, 0, lightClamp), lightAtten) * specularColor;
half3 diffuse = mainColor * lightColor;
#if defined(SGAME_WET) && defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
half thunderNDotL = saturate(dot(worldNormal, _SG_ThunderDirection));
half3 thunderDiffuse = mainColor * lerp(half3(0, 0, 0), _SG_ThunderColor, max(lightAtten, 0.1)) * thunderNDotL * _SG_ThunderStrength;
diffuse += thunderDiffuse;
#endif
#if defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
worldViewDir = normalize(worldViewDir);
half3 halfDir = normalize(worldLightDir + worldViewDir);
half NDotH = saturate(dot(worldNormal, halfDir));
half specularPow = SGamePow(NDotH, smoothness * 128.0);
half3 specular = specularColor.rgb * specularPow;
half3 finalColor = diffuse + specular;
#else
half3 finalColor = diffuse;
#endif
return finalColor;
}
inline half3 LambertLighting(half3 mainColor, half3 worldPos, half3 worldNormal, half lightAtten)
{
#if defined(SGAME_WET) && defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
mainColor = lerp(mainColor, mainColor * _SG_WetColor, _SG_WetFactor);
#endif
//Diffuse
Light mainLight = GetMainLight();
half3 worldLightDir = normalize(mainLight.direction);
half NDotL = saturate(dot(worldNormal, worldLightDir));
half3 lightColor = lerp(_SG_ShadowColor, mainLight.color.rgb, lightAtten * NDotL);
half3 diffuse = mainColor * lightColor;
#if defined(SGAME_WET) && defined(SGAME_QUALITY_PERFECT) || defined(SGAME_QUALITY_HIGH)
half thunderNDotL = saturate(dot(worldNormal, _SG_ThunderDirection));
half3 thunderDiffuse = mainColor * lerp(half3(0, 0, 0), _SG_ThunderColor, lightAtten) * NDotL * _SG_ThunderStrength;
diffuse += thunderDiffuse;
#endif
return diffuse;
}
inline half3 LambertLightingFwdBase(half3 mainColor, half3 worldPos, half3 worldNormal, half3 shLight, half lightAtten)
{
half3 ambient = GetAmbientColor(mainColor, shLight);
half3 baseLighting = LambertLighting(mainColor, worldPos, worldNormal, lightAtten);
half3 finalColor = ambient + baseLighting;
return finalColor;
}
inline half3 BlinnPhoneLightingFwdBase_CustomAmbient(half3 mainColor, half3 worldPos, half3 worldNormal, half3 worldViewDir, half3 shLight, half lightAtten, half3 specularColor, half smoothness)
{
half3 ambient = GetAmbientColor_Custom(mainColor, shLight);
half3 baseLighting = BlinnPhoneLighting(mainColor, worldPos, worldNormal, worldViewDir, specularColor, smoothness, lightAtten, 0.9);
half3 finalColor = clamp(ambient, 0, 0.65) + baseLighting;
return finalColor;
}
inline half3 BlinnPhoneLightingFwdBase_CustomLight(half3 mainColor, half3 worldPos, half3 worldNormal, half3 worldViewDir, half3 shLight, half lightAtten, half3 specularColor, half smoothness, half3 lightDir)
{
half3 ambient = GetAmbientColor(mainColor, shLight);
half3 baseLighting = BlinnPhoneLighting(mainColor, worldPos, worldNormal, worldViewDir, specularColor, smoothness, lightAtten, 3, 1, lightDir, 1);
half3 finalColor = ambient + baseLighting;
return finalColor;
}
inline half3 BlinnPhoneLightingFwdBase_CustomLightTerrain(half3 mainColor, half3 worldPos, half3 worldNormal, half3 worldViewDir, half3 shLight, half lightAtten, half3 specularColor, half smoothness, half3 lightDir)
{
half3 ambient = GetAmbientColor(mainColor, shLight);
half3 baseLighting = BlinnPhoneLighting(mainColor, worldPos, worldNormal, worldViewDir, specularColor, smoothness, lightAtten, 3, 1, lightDir, 1);
half3 finalColor = ambient + baseLighting;
return finalColor;
}
inline half3 BlinnPhoneLightingFwdBase(half3 mainColor, half3 worldPos, half3 worldNormal, half3 worldViewDir, half3 shLight, half lightAtten, half3 specularColor, half smoothness)
{
half3 ambient = GetAmbientColor(mainColor, shLight);
half3 baseLighting = BlinnPhoneLighting(mainColor, worldPos, worldNormal, worldViewDir, specularColor, smoothness, lightAtten);
half3 finalColor = ambient + baseLighting;
return finalColor;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif