367 lines
15 KiB
HLSL
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 |