Files
Fishing2/Assets/KriptoFX/WaterSystem2/WaterResources/Shaders/Resources/Common/KWS_WaterFragPass.cginc
2025-06-21 18:06:12 +08:00

588 lines
23 KiB
HLSL

#ifndef KWS_WATER_FRAG_PASS
#define KWS_WATER_FRAG_PASS
half4 fragWater(v2fWater i) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
float2 screenUV = i.screenPos.xy / i.screenPos.w;
float3 viewDir = GetWorldSpaceViewDirNorm(i.worldPosRefracted);
float surfaceDepthZ = i.screenPos.z / i.screenPos.w;
float surfaceDepthZEye = LinearEyeDepthUniversal(surfaceDepthZ);
float sceneZ = GetSceneDepth(screenUV);
float sceneZEye = LinearEyeDepthUniversal(sceneZ);
half surfaceMask = max(i.surfaceMask.x >= 0.999, i.surfaceMask.x <= 0.0001);
half exposure = GetExposure();
half alpha = GetSurfaceToSceneFading(sceneZEye, surfaceDepthZEye, 2.0);
float2 flowDirection = 0;
float foamMask = 0;
bool isDynamicWavesZone = false;
float shorelineFade = 1;
float riverMask = 0;
float3 turbidityColor = KWS_TurbidityColor;
float3 waterColor = KWS_DyeColor;
float transparent = KWS_Transparent;
float subsurfaceScatteringAdditionalMask = 0;
float waterfallMask = 0;
float4 colorData = float4(0, 0, 0, 0);
float3 dynamicWavesNormal = float3(0, 1, 0);
float borderFade = 0;
float dynamicWavesNormalMask = 0;
float flowSpeedMultiplier = 1;
float velocityLength = 0;
float dynamicWavesHeight = 0;
//return float4(i.surfaceMask.x, 0, 0, 1);
#if defined(KWS_USE_LOCAL_WATER_ZONES)
UNITY_LOOP
for (uint zoneIdx = 0; zoneIdx < KWS_WaterLocalZonesCount; zoneIdx++)
{
LocalZoneData zone = KWS_ZoneData_LocalZone[zoneIdx];
// if (zone.cutoutMode > 0)
// {
// float3 distanceToBox = abs(i.worldPosRefracted.xyz - zone.center.xyz) / zone.halfSize.xyz;
// float distanceToBorder = KWS_MAX(saturate(distanceToBox));
// float cutoutFadeFactor = saturate(smoothstep(0, zone.cutoutFadeFactor * 0.5, 1 - distanceToBorder));
// cutoutFadeFactor = 1 - KWS_Pow2(1 - cutoutFadeFactor);
// alpha = lerp(1 - cutoutFadeFactor, cutoutFadeFactor, zone.cutoutMode == 2);
// //return float4(distanceToBorder, 0, 0, 1);
// }
if (zone.clipWaterBelowZone)
{
float2 distanceToBox = abs(mul(i.worldPos.xz - zone.center.xz, zone.rotationMatrix)) / zone.halfSize.xz;
float distanceToBorder = max(distanceToBox.x, distanceToBox.y);
float zoneMinHeight = zone.center.y - zone.halfSize.y;
if (distanceToBorder < 1.1 && i.worldPosRefracted.y < zoneMinHeight) discard;
}
if (zone.overrideColorSettings > 0.5)
{
float tEntry;
float3 sceneWorldPos = GetWorldSpacePositionFromDepth(screenUV, sceneZ);
float3 surfaceOffset = float3(0, max(0, zone.center.y + zone.halfSize.y - i.worldPosRefracted.y) * 0.5f, 0);
float density = 0;
if (zone.useSphereBlending > 0.5)
{
density = KWS_SDF_SphereDensity(i.worldPosRefracted, normalize(sceneWorldPos - i.worldPosRefracted), zone.center, zone.halfSize, length(i.worldPosRefracted - sceneWorldPos), tEntry);
}
else
{
float2 boxSDF = KWS_SDF_IntersectionBox(i.worldPosRefracted, normalize(sceneWorldPos - i.worldPosRefracted), zone.rotationMatrix, zone.center, zone.halfSize);
density = boxSDF.x < boxSDF.y && boxSDF.y > 0 && boxSDF.x < length(i.worldPosRefracted - sceneWorldPos);
tEntry = boxSDF.x;
}
if (density > 0)
{
density = saturate(density * 2);
density = lerp(0, density, saturate(transparent / max(1, tEntry)));
transparent = lerp(transparent, zone.transparent, density);
turbidityColor = lerp(turbidityColor, zone.turbidityColor, density);
waterColor = lerp(waterColor, zone.waterColor, density);
}
}
}
#endif
if (alpha < 0.001) return 0;
// return float4(1, 0, 0, 1);
#if defined(KWS_USE_DYNAMIC_WAVES)
uint zoneIndexOffset = 0;
uint zoneIndexCount = 0;
isDynamicWavesZone = GetTileRange(i.worldPos, zoneIndexOffset, zoneIndexCount);
if (isDynamicWavesZone)
{
float maxIterrations = 0;
for (uint zoneIndex = zoneIndexOffset; zoneIndex < zoneIndexCount; zoneIndex++)
{
ZoneData zone = (ZoneData)0;
if (GetWaterZone(i.worldPos, zoneIndex, zone))
{
//return float4( frac(zoneIndex * 0.121345), 0, 0, 1);
//return float4(zone.uv, 0, 1);
float4 dynamicWaves = GetDynamicWavesZone(zone.id, zone.uv);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalDataBicubic(zone.id, zone.uv); //(wetmap, shoreline mask, foam mask, wetDepth)
float3 zoneNormal = GetDynamicWavesZoneNormalsBicubic(zone.id, zone.uv).xyz;
float zoneFade = GetDynamicWavesBorderFading(zone.uv);
float shorelineMask = dynamicWavesAdditionalData.y;
zoneNormal = lerp(float3(0, 1, 0), zoneNormal, zoneFade);
flowSpeedMultiplier *= zone.flowSpeedMultiplier;
float waterfallThreshold = GetDynamicWavesWaterfallTreshold(zoneNormal) * zoneFade;
dynamicWaves.xy = lerp(dynamicWaves.xy, dynamicWaves.xy * 0.2, waterfallThreshold);
flowDirection = (flowDirection + dynamicWaves.xy);
shorelineFade *= shorelineMask;
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, zoneNormal);
velocityLength += length(dynamicWaves.xy);
dynamicWavesHeight += dynamicWaves.z;
//zoneFade *= lerp(saturate(dynamicWaves.z * dynamicWaves.z * 10), 1, dynamicWavesAdditionalData.y);
borderFade = saturate(borderFade + zoneFade);
foamMask = max(foamMask, dynamicWavesAdditionalData.z * zoneFade);
waterfallThreshold *= exp(-dynamicWaves.z * 0.35);
float foamWaveThreshold = 1-saturate(lerp(0.5, saturate(waterfallThreshold * 5), shorelineMask));
//foamMask *= lerp(0, 1, foamWaveThreshold * foamMask * foamMask);
//transparent *= lerp(1, 0.25, waterfallThreshold);
//subsurfaceScatteringAdditionalMask += saturate(waterfallThreshold * 0.5);
waterfallMask = saturate(waterfallMask + waterfallThreshold);
#ifdef KWS_DYNAMIC_WAVES_USE_COLOR
float4 zoneColorData = GetDynamicWavesZoneColorData(zone.id, zone.uv);
zoneColorData.rgb = lerp(zoneColorData.rgb, zoneColorData.rgb * 0.35, saturate(zoneColorData.a * zoneColorData.a + zoneColorData.a * 2));
turbidityColor = lerp(turbidityColor, zoneColorData.rgb, zoneColorData.a);
waterColor = lerp(waterColor, zoneColorData.rgb, saturate(zoneColorData.a * 2));
transparent = lerp(transparent, DYNAMIC_WAVE_COLOR_MAX_TRANSPARENT, zoneColorData.a);
colorData = max(colorData, zoneColorData);
#endif
}
}
velocityLength *= KWS_Pow2(borderFade);
dynamicWavesNormalMask = saturate(dynamicWavesHeight * 0.5 * velocityLength) * KWS_Pow3(borderFade);
flowDirection *= KWS_Pow2(borderFade);
}
#endif
#if defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
float2 movableZoneUV = 0;
if (GetWaterZoneMovable(i.worldPos, movableZoneUV))
{
isDynamicWavesZone = true;
float4 dynamicWaves = GetDynamicWavesZoneMovable(movableZoneUV);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalDataMovable(movableZoneUV); //(wetmap, shoreline mask, foam mask, wetDepth)
float3 zoneNormal = GetDynamicWavesZoneNormalsMovable(movableZoneUV).xyz;
float zoneFade = GetDynamicWavesBorderFading(movableZoneUV);
flowSpeedMultiplier *= KWS_MovableZoneFlowSpeedMultiplier;
zoneNormal = lerp(float3(0, 1, 0), zoneNormal, zoneFade);
//zoneFade *= lerp(saturate(dynamicWaves.z * dynamicWaves.z * 10), 1, dynamicWavesAdditionalData.y);
flowDirection = (flowDirection + dynamicWaves.xy);
foamMask = max(foamMask, dynamicWavesAdditionalData.z * zoneFade);
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, zoneNormal);
borderFade = saturate(borderFade + zoneFade);
dynamicWavesHeight += dynamicWaves.z;
//dynamicWavesNormalMask = max(dynamicWavesNormalMask, saturate(dynamicWaves.z * 0.5 * length(dynamicWaves.xy)) * KWS_Pow3(borderFade));
velocityLength *= KWS_Pow2(borderFade);
dynamicWavesNormalMask = saturate(dynamicWavesHeight * 0.5 * velocityLength) * KWS_Pow3(borderFade);
flowDirection *= KWS_Pow2(borderFade);
}
#endif
///////////////////////////////////////////////////////////// NORMAL ////////////////////////////////////////////////////////////////////////////////////////////////////////
float3 wavesNormalFoam = GetFftWavesNormalFoam(i.worldPos, i.windAttenuation);
float3 tangentNormal = float3(wavesNormalFoam.x, 1, wavesNormalFoam.z);
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
if (isDynamicWavesZone && borderFade > 0.0)
{
riverMask = saturate(i.worldPosRefracted.y - KWS_WaterPosition.y - 4) * (1 - shorelineFade) * borderFade;
float windAttenuationWithSmallZ = lerp(1, saturate(velocityLength) * (1 - shorelineFade), riverMask);
//return float4(tangentNormal.xz, 0, 1);
float3 dynamicWavesFlowNormal = GetFftWavesNormalFoamWithFlowmap(i.worldPos, flowDirection * borderFade * 1, 4.0 * flowSpeedMultiplier, KWS_ScaledTime * KWS_DynamicWavesTimeScale);
dynamicWavesFlowNormal.xz *= lerp(0.1, 1.0 * RIVER_FLOW_NORMAL_MULTIPLIER, windAttenuationWithSmallZ);
dynamicWavesFlowNormal = lerp(dynamicWavesNormal, dynamicWavesFlowNormal, riverMask);
//tangentNormal = lerp(tangentNormal, dynamicWavesNormal, saturate(dynamicWavesHeight * 0.15 + velocityLength * velocityLength * 0.15) * 0.75);
tangentNormal = lerp(tangentNormal, dynamicWavesFlowNormal, saturate(dynamicWavesNormalMask * 0.7));
tangentNormal = lerp(tangentNormal, dynamicWavesFlowNormal, riverMask);
//return float4(dynamicWavesNormalMask, 0, 0, 1);
}
#endif
if (KWS_UseOceanFoam)
{
//return float4(wavesNormalFoam.yyy, 1);
foamMask = max(foamMask, wavesNormalFoam.y * surfaceMask * shorelineFade * KWS_Pow3(i.windAttenuation));
}
tangentNormal = lerp(float3(0, 1, 0), tangentNormal, surfaceMask * alpha);
float3 worldNormal = KWS_BlendNormals(tangentNormal, i.worldNormal);
//worldNormal = KWS_GetDerivativeNormal(i.worldPosRefracted, _ProjectionParams.x);
///////////////////////////////////////////////////////////// end normal ////////////////////////////////////////////////////////////////////////////////////////////////////////
//return float4(worldNormal.xz, 0, 1);
///////////////////////////////////////////////////////////////////// REFRACTION ///////////////////////////////////////////////////////////////////
float2 refractionUV;
half3 refraction;
//todo surfaceMask > 0.5
#ifdef KWS_USE_REFRACTION_IOR
float3 refractionPos = float3(i.worldPos.x, i.worldPosRefracted.y, i.worldPos.z);
refractionUV = GetRefractedUV_IOR(viewDir, worldNormal, refractionPos, sceneZEye, surfaceDepthZEye, transparent);
#else
refractionUV = GetRefractedUV_Simple(screenUV, worldNormal);
#endif
refractionUV = lerp(screenUV, refractionUV, surfaceMask);
refractionUV += waterfallMask * clamp(flowDirection * 0.5, -0.25, 0.25) * lerp(1.0, RIVER_FLOW_FRESNEL_MULTIPLIER * 0.5, riverMask);
float refractedSceneZ = GetSceneDepth(refractionUV);
float refractedSceneZEye = LinearEyeDepthUniversal(refractedSceneZ);
FixRefractionSurfaceLeaking(surfaceDepthZEye, sceneZ, sceneZEye, screenUV, refractedSceneZ, refractedSceneZEye, refractionUV);
//todo surfaceMask > 0.5
#ifdef KWS_USE_REFRACTION_DISPERSION
refraction = GetSceneColorWithDispersion(refractionUV, KWS_RefractionDispersionStrength);
#else
refraction = GetSceneColor(refractionUV);
#endif
//refraction *= float3(0.85, 0.87, 0.9);
//return float4(refraction, 1);
///////////////////////////////////////////////////////////// end refraction ////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// UNDERWATER ///////////////////////////////////////////////////////////////////
#if defined(KWS_USE_LOCAL_WATER_ZONES)
//transparent = GetWaterLocalZonesTransparent(screenUV);
//if (transparent < 0.99f) return 0;
#endif
//waterfallMask
float2 volumeDepth = GetWaterVolumeDepth(screenUV, surfaceDepthZ, refractedSceneZ, 0);
half4 volumeLight = GetVolumetricLightWithAbsorbtion(screenUV, lerp(refractionUV, screenUV, waterfallMask), transparent, turbidityColor, waterColor, refraction, volumeDepth, exposure, 0);
if (surfaceMask < 0.5) return float4(volumeLight.xyz, 1);
float depthAngleFix = (surfaceMask < 0.5 || KWS_MeshType == KWS_MESH_TYPE_CUSTOM_MESH) ? 0.25 : saturate(GetWorldSpaceViewDirNorm(i.worldPos - float3(0, KWS_WindSpeed * 0.5, 0)).y);
float fade = GetWaterRawFade(i.worldPos, surfaceDepthZEye, refractedSceneZEye, surfaceMask, depthAngleFix);
half3 underwaterColor = volumeLight.xyz;
float4 foamTex = 0;
if(KWS_UseOceanFoam)
{
foamTex += KW_FluidsFoamTex.Sample(sampler_linear_repeat, i.worldPos.xz * 0.05).xyzw * (1-borderFade);
}
if (isDynamicWavesZone || KWS_UseOceanFoam || KWS_UseIntersectionFoam)
{
foamTex += Texture2DSampleFlowmapJump(KW_FluidsFoamTex, sampler_linear_repeat, i.worldPos.xz * 0.03, flowDirection * 0.07, KWS_ScaledTime * 1.0 * KWS_DynamicWavesTimeScale * flowSpeedMultiplier ).xyzw * borderFade;
float foamCutout = saturate((pow(abs(foamTex.a), 1.5) - (1 - sqrt(foamMask)) * 1.0));
float bubblesCutout = saturate(foamTex.y - (1 - pow(abs(foamMask), 0.25)) * 1.0);
float3 bubblesColor = saturate(GetSurfaceLightWithAbsorbtionByDistance(screenUV, transparent, turbidityColor, waterColor, (2.5 - foamMask), exposure));
float3 surfaceColor = turbidityColor;
//#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_DYNAMIC_WAVES_ATLAS)
// bubblesColor *= saturate(dynamicWaves.z * 0.5);
//#endif
float3 foamColor = 0;
foamColor += foamCutout;
foamColor += bubblesColor * bubblesCutout * 0.15;
foamColor += bubblesColor * foamMask * 0.5;
foamColor = saturate(foamColor) * KWS_Pow3(alpha);
//float4 foamVolumeLight = volumeLight;
//foamVolumeLight.a = saturate(foamVolumeLight.a + 0.1);
//foamColor *= GetVolumetricSurfaceLight(foamVolumeLight, worldNormal, exposure);
//foamColor *= KWS_ComputeLighting(i.worldPosRefracted, 0.1, true, screenUV);
foamColor *= clamp(GetVolumetricSurfaceLight(screenUV), 0, 1.25);
//return float4(KWS_ComputeLighting(i.worldPosRefracted, 0.1, false, screenUV), 1);
foamColor *= lerp(1, colorData.rgb, saturate(colorData.a * 1.25));
underwaterColor = lerp(underwaterColor + foamColor, foamColor, colorData.a);
}
//return float4(volumeLight.xyz, 1);
float3 subsurfaceScatteringColor = ComputeSSS(screenUV, GetWaterSSS(screenUV), underwaterColor, volumeLight.a, transparent);
underwaterColor += subsurfaceScatteringColor * 10;
///////////////////////////////////////////////////////////// end underwater ////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// REFLECTION ////////////////////////////////////////////////////////////////////////////////////////////////////////
float3 reflDir = reflect(-viewDir, worldNormal);
reflDir.y *= sign(dot(reflDir, float3(0, 1, 0)));
float3 reflection = 0;
#if defined(KWS_SSR_REFLECTION) || defined(KWS_USE_PLANAR_REFLECTION)
float2 refl_uv = GetScreenSpaceReflectionUV(reflDir, screenUV + tangentNormal.xz * 0.5);
#endif
#if KWS_USE_PLANAR_REFLECTION
reflection = GetPlanarReflectionWithClipOffset(refl_uv) * exposure;
#else
#if KWS_USE_REFLECTION_PROBES
reflection = KWS_GetReflectionProbeEnv(screenUV, surfaceDepthZEye, i.worldPosRefracted, reflDir, KWS_SkyLodRelativeToWind, exposure);
#else
reflection = KWS_GetSkyColor(reflDir, KWS_SkyLodRelativeToWind, exposure);
#endif
#endif
#if KWS_SSR_REFLECTION
float4 ssrReflection = GetScreenSpaceReflectionWithStretchingMask(refl_uv, i.worldPosRefracted);
reflection = lerp(reflection, ssrReflection.rgb, ssrReflection.a);
#endif
reflection *= surfaceMask * (1 - waterfallMask);
///////////////////////////////////////////////////////////// end reflection ////////////////////////////////////////////////////////////////////////////////////////////////////////
half waterFresnel = ComputeWaterFresnel(worldNormal, viewDir);
waterFresnel *= lerp(1.0, RIVER_FLOW_FRESNEL_MULTIPLIER, riverMask);
waterFresnel *= surfaceMask * (1 - waterfallMask);
half3 finalColor = lerp(underwaterColor, reflection, waterFresnel);
#if KWS_REFLECT_SUN
float3 sunReflection = ComputeSunlight(worldNormal, viewDir, GetMainLightDir(), GetMainLightColor(exposure), volumeLight.a, surfaceDepthZEye, _ProjectionParams.z, transparent);
float sunFadeFactor = saturate(abs(sceneZEye - surfaceDepthZEye));
sunFadeFactor = KWS_Pow5(sunFadeFactor) * saturate(1 - waterfallMask * 2);
finalColor += sunReflection * (1 - saturate(KWS_Pow3(foamMask * 3))) * sunFadeFactor;
#endif
half3 fogColor;
half3 fogOpacity;
GetInternalFogVariables(i.pos, viewDir, surfaceDepthZ, surfaceDepthZEye, i.worldPosRefracted, fogColor, fogOpacity);
fogOpacity = saturate(fogOpacity * 1.5);
finalColor = ComputeInternalFog(finalColor, fogColor, fogOpacity);
finalColor = ComputeThirdPartyFog(finalColor, i.worldPos, screenUV, i.screenPos.z);
finalColor += srpBatcherFix;
//return float4(alpha, 0, 0, 1);
return float4(finalColor, alpha);
}
struct FragmentOutput
{
half4 pass1 : SV_Target0;
half2 pass2 : SV_Target1;
};
FragmentOutput fragDepth(v2fDepth i, float facing : VFACE) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
FragmentOutput o = (FragmentOutput)0;
float facingColor = 0.75 - facing * 0.25;
float2 screenUV = i.screenPos.xy / i.screenPos.w;
float z = i.screenPos.z / i.screenPos.w;
float sceneDepth = GetSceneDepth(screenUV);
#ifdef KWS_PRE_PASS_BACK_FACE
float mask = i.surfaceMask.x < 0.9999 ? 0.1 : 1;
#else
float mask = facing > 0 ? 0.25 : 0.75;
if (i.surfaceMask.x < 0.9999)
{
mask = facing > 0.0 ? 0.1 : 1;
}
#endif
float2 flowDirection = 0;
bool isDynamicWavesZone = false;
float3 dynamicWavesNormal = float3(0, 1, 0);
float dynamicWavesNormalMask = 0;
float borderFade = 0;
float flowSpeedMultiplier = 1;
float velocityLength = 0;
#if defined(KWS_USE_DYNAMIC_WAVES)
float dynamicWavesHeight = 0;
uint zoneIndexOffset = 0;
uint zoneIndexCount = 0;
isDynamicWavesZone = GetTileRange(i.worldPos, zoneIndexOffset, zoneIndexCount);
if (isDynamicWavesZone)
{
for (uint zoneIndex = zoneIndexOffset; zoneIndex < zoneIndexCount; zoneIndex++)
{
ZoneData zone = (ZoneData)0;
if (GetWaterZone(i.worldPos, zoneIndex, zone))
{
float4 dynamicWaves = GetDynamicWavesZone(zone.id, zone.uv);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalData(zone.id, zone.uv); //(wetmap, shoreline mask, foam mask, wetDepth)
float3 zoneNormal = GetDynamicWavesZoneNormals(zone.id, zone.uv).xyz;
float zoneFade = GetDynamicWavesBorderFading(zone.uv);
flowSpeedMultiplier *= zone.flowSpeedMultiplier;
flowDirection = NormalizeDynamicWavesVelocity(flowDirection + dynamicWaves.xy);
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, zoneNormal);
dynamicWavesHeight += dynamicWaves.z;
velocityLength += length(dynamicWaves.xy);
zoneFade *= lerp(saturate(dynamicWaves.z * dynamicWaves.z * 10), 1, dynamicWavesAdditionalData.y);
borderFade = saturate(borderFade + zoneFade);
}
}
dynamicWavesNormalMask = saturate(dynamicWavesHeight * 0.5 * velocityLength) * KWS_Pow3(borderFade);
}
#endif
#if defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
float2 movableZoneUV = 0;
if (GetWaterZoneMovable(i.worldPos, movableZoneUV))
{
isDynamicWavesZone = true;
float4 dynamicWaves = GetDynamicWavesZoneMovable(movableZoneUV);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalDataMovable(movableZoneUV); //(wetmap, shoreline mask, foam mask, wetDepth)
float3 zoneNormal = GetDynamicWavesZoneNormalsMovable(movableZoneUV).xyz;
flowSpeedMultiplier *= KWS_MovableZoneFlowSpeedMultiplier;
float zoneFade = GetDynamicWavesBorderFading(movableZoneUV);
zoneFade *= lerp(saturate(dynamicWaves.z * dynamicWaves.z * 10), 1, dynamicWavesAdditionalData.y);
flowDirection = NormalizeDynamicWavesVelocity(flowDirection + dynamicWaves.xy);
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, zoneNormal);
borderFade = saturate(borderFade + zoneFade);
velocityLength += length(dynamicWaves.xy);
dynamicWavesNormalMask = max(dynamicWavesNormalMask, saturate(dynamicWaves.z * 0.5 * length(dynamicWaves.xy)) * KWS_Pow3(borderFade));
}
#endif
///////////////////////////////////////////////////////////// NORMAL ////////////////////////////////////////////////////////////////////////////////////////////////////////
float3 wavesNormalFoam = GetFftWavesNormalFoam(i.worldPos, i.windAttenuation);
float3 tangentNormal = float3(wavesNormalFoam.x, 1, wavesNormalFoam.z);
float3 tangentNormalScatter = GetFftWavesNormalLod(i.worldPos, KWS_WATER_SSR_NORMAL_LOD);
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
if (isDynamicWavesZone)
{
float riverMask = saturate(i.worldPos.y - KWS_WaterPosition.y - 4);
float windAttenuationWithSmallZ = lerp(1, saturate(velocityLength), borderFade * riverMask);
float3 dynamicWavesFlowNormal = GetFftWavesNormalFoamWithFlowmap(i.worldPos, flowDirection * borderFade * 1, 4.0 * flowSpeedMultiplier, KWS_ScaledTime * KWS_DynamicWavesTimeScale);
dynamicWavesFlowNormal.xz *= lerp(0.1, 1.0, windAttenuationWithSmallZ);
dynamicWavesFlowNormal = lerp(dynamicWavesNormal, dynamicWavesFlowNormal, borderFade * riverMask);
tangentNormal = lerp(tangentNormal, dynamicWavesFlowNormal, borderFade * riverMask);
}
#endif
float3 worldNormal = KWS_BlendNormals(tangentNormal, i.worldNormal);
worldNormal *= i.surfaceMask.x > 0.9999 ? 1 : 0;
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
if (isDynamicWavesZone)
{
float underwaterRefractionFix = 1 - saturate(1.25 * saturate(1 - dot(dynamicWavesNormal, float3(0, 1, 0))));
worldNormal *= underwaterRefractionFix;
}
#endif
float transparent = KWS_Transparent;
// #if defined(KWS_USE_LOCAL_WATER_ZONES)
//
// UNITY_LOOP
// for (uint zoneIdx = 0; zoneIdx < KWS_WaterLocalZonesCount; zoneIdx++)
// {
// LocalZoneData zone = KWS_ZoneData_LocalZone[zoneIdx];
//
// float2 distanceToBox = abs(i.worldPos.xz - zone.center.xz) / zone.halfSize.xz;
// float distanceToBorder = max(distanceToBox.x, distanceToBox.y);
// float zoneMinHeight = zone.center.y - zone.halfSize.y;
//
// if (distanceToBorder < 1.1 && i.worldPosRefracted.y < zoneMinHeight) discard;
// }
//
// #endif
float3 viewDir = GetWorldSpaceViewDirNorm(i.worldPosRefracted);
float3 lightDir = GetMainLightDir();
float distanceToCamera = GetWorldToCameraDistance(i.worldPos);
float dotVal = dot(lightDir, float3(0, 1, 0));
float sunAngleAttenuation = smoothstep(-0.1, 1.0, dotVal);
float3 refractedVector = normalize(refract(-viewDir, tangentNormalScatter, 0.66));
float scattering = pow(saturate(dot(refractedVector, lightDir)), 16);
float sss = saturate(scattering * sunAngleAttenuation * 5000);
half tensionMask = 0;
#ifdef KWS_USE_HALF_LINE_TENSION
tensionMask = abs(i.localHeightAndTensionMask.y) * KWS_InstancingWaterScale.y * lerp(40, 10, KWS_UnderwaterHalfLineTensionScale);
if (tensionMask >= 0.99) tensionMask = ((1.2 - tensionMask) * 5);
if (i.surfaceMask.x > 0.9999 || facing < 0 || z <= sceneDepth) tensionMask = 0;
tensionMask *= 1 - saturate(distanceToCamera * 0.1);
#endif
o.pass1 = half4(transparent / 100.0, mask, sss, tensionMask);
o.pass2 = worldNormal.xz;
return o;
}
#endif