#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