Files
Fishing2/Assets/KriptoFX/WaterSystem2/WaterResources/Shaders/Resources/Common/KWS_WaterFragPass.cginc
2025-11-16 22:37:55 +08:00

743 lines
29 KiB
HLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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);
float distanceToCamera = GetWorldToCameraDistance(i.worldPos);
float3 sceneWorldPos = GetWorldSpacePositionFromDepth(screenUV, sceneZ);
float waterDepth = i.worldPosRefracted.y - sceneWorldPos.y;
waterDepth = lerp(clamp(abs(surfaceDepthZEye - sceneZEye) * 0.1, 0, 10), waterDepth, 1-KWS_Pow10(1-viewDir.y));
half surfaceMask = max(i.surfaceMask.x >= 0.999, i.surfaceMask.x <= 0.0001);
half exposure = GetExposure();
half alpha = 1;
float3 turbidityColor = KWS_TurbidityColor;
float3 waterColor = KWS_WaterColor;
float transparent = KWS_Transparent;
float localZoneDensity = 0;
bool isDynamicWavesZone = false;
float4 foamData = float4(1, 2.25, 1, 1);
float shorelineMask = 1;
float riverMask = 0;
float waterfallMask = 0;
float foamMask = 0;
float2 flowDirection = 0;
float3 dynamicWavesNormal = float3(0, 1, 0);
float borderFade = 0;
float dynamicWavesNormalMask = 0;
float flowSpeedMultiplier = 1;
float velocityLength = 0;
float dynamicWavesHeight = 0;
float dynamicWavesFoamAlpha = 1;
float4 colorData = float4(0, 0, 0, 0);
#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.overrideHeight > 0.5 && 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;
localZoneDensity = 1;
}
if (zone.overrideColorSettings > 0.5)
{
float tEntry=0;
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.xyz, zone.halfSize.x, 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.xyz, density);
waterColor = lerp(waterColor, zone.waterColor.xyz, density);
localZoneDensity = lerp(localZoneDensity, 1, density);
}
}
}
#endif
if (alpha < 0.001) return 0;
float4 advectedUV = 0;
bool useAdvectedUV = false;
bool useDynamicWavesFoamTexture = false;
#ifdef KWS_USE_ZONE_INSTANCE
isDynamicWavesZone = true;
float4 dynamicWaves = GetDynamicWavesZone(i.uv);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalDataBicubic(i.uv); //(wetmap, shoreline mask, foam mask, wetDepth)
float3 zoneNormal = i.worldNormal;
float zoneFade = GetDynamicWavesBorderFading(i.uv);
zoneNormal = lerp(float3(0, 1, 0), zoneNormal, zoneFade);
flowSpeedMultiplier *= KWS_DynamicWavesZoneFlowSpeedMultiplier;
dynamicWavesFoamAlpha *= KWS_DynamicWavesZoneFoamData.w;
foamData.xyz = KWS_DynamicWavesZoneFoamData;
foamData.w = foamData.z *(KWS_DynamicWavesZoneSize.z / KWS_DynamicWavesZoneSize.x);
useDynamicWavesFoamTexture = KWS_DynamicWavesUseFoamTexture;
useAdvectedUV = false; //baked mode can't use advected textures
float waterfallThreshold = GetDynamicWavesWaterfallTreshold(zoneNormal) * zoneFade;
dynamicWaves.xy = lerp(dynamicWaves.xy, dynamicWaves.xy * 0.2, waterfallThreshold);
flowDirection = (flowDirection + dynamicWaves.xy);
shorelineMask = max(dynamicWavesAdditionalData.y, 1 - zoneFade);
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, zoneNormal);
velocityLength += length(dynamicWaves.xy);
dynamicWavesHeight += dynamicWaves.z;
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));
waterfallMask = saturate(waterfallMask + waterfallThreshold);
#ifdef KWS_USE_COLORED_DYNAMIC_WAVES
float4 zoneColorData = GetDynamicWavesZoneColorData(i.uv);
float colorTransparencyFactor = (dot(zoneColorData.rgb, 0.33));
zoneColorData.a = lerp(zoneColorData.a, 0, colorTransparencyFactor);
zoneColorData.rgb = lerp(zoneColorData.rgb, zoneColorData.rgb * 0.35, saturate(zoneColorData.a * zoneColorData.a + zoneColorData.a * 2));
zoneColorData.a = saturate(zoneColorData.a * 2);
turbidityColor = lerp(turbidityColor, zoneColorData.rgb, zoneColorData.a);
waterColor = lerp(waterColor, zoneColorData.rgb, zoneColorData.a);
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_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES)
float3 dynamicWavesMapUV = GetDynamicWavesMapUV(i.worldPosRefracted, distanceToCamera);
isDynamicWavesZone = !IsOutsideUvBorders(dynamicWavesMapUV.xy);
if (isDynamicWavesZone)
{
float4 dynamicWaves = GetDynamicWavesMapBicubic(dynamicWavesMapUV);
DynamicWavesAdditionalData additionalData = GetDynamicWavesAdditionalMapBicubic(dynamicWavesMapUV);
dynamicWavesNormal = GetDynamicWavesNormalMap(dynamicWavesMapUV);
float waterfallThreshold = GetDynamicWavesWaterfallTreshold(dynamicWavesNormal);
dynamicWaves.xy = lerp(dynamicWaves.xy, dynamicWaves.xy * 0.2, waterfallThreshold);
borderFade = additionalData.zoneFade;
waterfallThreshold *= exp(-dynamicWaves.z * 0.35);
waterfallMask = saturate(waterfallMask + waterfallThreshold);
foamMask = additionalData.foamMask * borderFade;
flowDirection = dynamicWaves.xy * borderFade;
shorelineMask = max(additionalData.shorelineMask, 1-borderFade);
velocityLength = length(dynamicWaves.xy) * borderFade;
dynamicWavesHeight = dynamicWaves.z;
ZoneData zone = KWS_ZoneData[additionalData.zoneID];
useAdvectedUV = zone.useAdvectedUV;
useDynamicWavesFoamTexture = zone.useFoamTexture;
flowSpeedMultiplier = zone.flowSpeedMultiplier;
dynamicWavesFoamAlpha *= zone.foamData.w;
foamData.xyz = zone.foamData.xyz;
foamData.w = foamData.z * (zone.halfSize.z / zone.halfSize.x);
foamMask *= useDynamicWavesFoamTexture;
if (zone.useAdvectedUV) advectedUV = GetDynamicWavesAdvectedUVMap(dynamicWavesMapUV);
#ifdef KWS_USE_COLORED_DYNAMIC_WAVES
float4 zoneColorData = GetDynamicWavesColorMap(dynamicWavesMapUV);
float colorTransparencyFactor = (dot(zoneColorData.rgb, 0.33));
zoneColorData.a = lerp(zoneColorData.a, 0, colorTransparencyFactor);
zoneColorData.rgb = lerp(zoneColorData.rgb, zoneColorData.rgb * 0.35, saturate(zoneColorData.a * zoneColorData.a + zoneColorData.a * 2));
zoneColorData.a = saturate(zoneColorData.a * 2);
turbidityColor = lerp(turbidityColor, zoneColorData.rgb, zoneColorData.a);
waterColor = lerp(waterColor, zoneColorData.rgb, zoneColorData.a);
//transparent = lerp(transparent, DYNAMIC_WAVE_COLOR_MAX_TRANSPARENT, zoneColorData.a);
colorData = zoneColorData;
#endif
}
#endif
alpha = lerp(1-KWS_Pow5(1-borderFade), alpha, KWS_RenderOcean);
if (alpha < 0.001) return 0;
float2 flowDirectionNormalized = NormalizeDynamicWavesVelocity(flowDirection);
float noiseMask = GetNoiseMask(i.worldPos.xz, 1, 1);
///////////////////////////////////////////////////////////// NORMAL ////////////////////////////////////////////////////////////////////////////////////////////////////////
float3 tangentNormal = float3(0, 1, 0);
float oceanFoamMask = 0;
#if defined(KWS_USE_OCEAN_RENDERING)
float3 wavesNormalFoam = GetFftWavesNormalFoam(i.worldPos, i.windAttenuation);
tangentNormal = float3(wavesNormalFoam.x, 1, wavesNormalFoam.z);
tangentNormal = lerp(float3(0, 1, 0), tangentNormal, any(fwidth(i.worldPos.xz))); //fix horizontal flickering
oceanFoamMask = wavesNormalFoam.y * noiseMask;
#endif
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES) || defined(KWS_USE_ZONE_INSTANCE)
if (isDynamicWavesZone && borderFade > 0.0)
{
riverMask = saturate(i.worldPosRefracted.y - KWS_WaterLevel - 3) * (1 - shorelineMask);
float flowSpeed = lerp(0.25, 0.5, riverMask);
float3 dynamicWavesFlowNormal = Texture2DSampleFlowmapJumpStochastic(KWS_WaterDynamicWavesFlowMapNormal, sampler_linear_repeat, i.worldPos.xz * 0.05, flowDirectionNormalized * flowSpeed, KWS_ScaledTime * 1 * flowSpeedMultiplier, 5).xzy * 2 - 1;
dynamicWavesFlowNormal.z *= -1;
dynamicWavesFlowNormal.xz *= RIVER_FLOW_NORMAL_MULTIPLIER;
dynamicWavesFlowNormal = lerp(float3(0, 1, 0), dynamicWavesFlowNormal, riverMask * saturate(velocityLength - 0.15));
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, dynamicWavesFlowNormal);
tangentNormal = lerp(KWS_BlendNormals(dynamicWavesNormal, tangentNormal), dynamicWavesNormal, saturate((1-shorelineMask) - 0.2));
}
#endif
#if defined(KWS_USE_OCEAN_RENDERING)
if (KWS_UseOceanFoam)
{
//return float4(wavesNormalFoam.yyy, 1);
foamMask = max(foamMask, oceanFoamMask * surfaceMask * shorelineMask * KWS_Pow3(i.windAttenuation));
}
#endif
tangentNormal = lerp(float3(0, 1, 0), tangentNormal, surfaceMask * alpha);
#ifdef KWS_USE_ZONE_INSTANCE
float3 worldNormal = tangentNormal;
#else
float3 worldNormal = KWS_BlendNormals(tangentNormal, i.worldNormal);
#endif
//worldNormal = KWS_GetDerivativeNormal(i.worldPosRefracted, _ProjectionParams.x);
///////////////////////////////////////////////////////////// end normal ////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// REFRACTION ///////////////////////////////////////////////////////////////////
half3 refraction;
float2 refractionUV;
//todo surfaceMask > 0.5
#ifdef KWS_USE_REFRACTION_IOR
float3 refractionPos = float3(i.worldPos.x, i.worldPosRefracted.y, i.worldPos.z);
float riverRefractionMultiplier = lerp(1, 3, saturate(dynamicWavesHeight));
refractionUV = GetRefractedUV_IOR(viewDir, worldNormal, refractionPos, sceneZEye, surfaceDepthZEye, transparent, clamp(waterDepth * riverRefractionMultiplier, 0.1, KWS_MAX_TRANSPARENT));
/* //todo fix alpha
float3 refractedWorldPosDepth = GetWorldSpacePositionFromDepth(refractionUV, GetSceneDepth(refractionUV));
waterDepth = i.worldPosRefracted.y - refractedWorldPosDepth.y;
waterDepth = lerp(clamp(abs(surfaceDepthZEye - sceneZEye) * 0.1, 0, 10), waterDepth, 1-KWS_Pow10(1-viewDir.y));
refractionUV = GetRefractedUV_IOR(viewDir, worldNormal, refractionPos, sceneZEye, surfaceDepthZEye, transparent, clamp(waterDepth * riverRefractionMultiplier, 0.1, KWS_MAX_TRANSPARENT));
*/
#else
refractionUV = GetRefractedUV_Simple(screenUV, worldNormal);
#endif
refractionUV = lerp(screenUV, refractionUV, surfaceMask);
refractionUV += waterfallMask * clamp(flowDirectionNormalized * 0.5, -0.25, 0.25) * lerp(1.0, RIVER_FLOW_FRESNEL_MULTIPLIER * 0.5, riverMask) * (1.1-saturate(distanceToCamera * 0.01)) * saturate(waterDepth * 0.5);
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 ////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// CAUSTIC ///////////////////////////////////////////
#if defined(KWS_USE_CAUSTIC)
float3 refractedWorldPos = GetWorldSpacePositionFromDepth(refractionUV, refractedSceneZ);
float2 causticUV = refractedWorldPos.xz;
float3 oceanCaustic = 0;
float3 zoneCaustic = 0;
float zoneCausticFade = KWS_Pow2(borderFade);
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES) || defined(KWS_USE_ZONE_INSTANCE)
if (isDynamicWavesZone && zoneCausticFade > 0.0)
{
float causticNoiseMask = GetNoiseMask(causticUV, 2.5, 7);
causticNoiseMask = saturate(noiseMask * causticNoiseMask + 0.1 + velocityLength * 0.25);
//todo add high quality option
/*
float3 dynamicWavesMapUVRefracted = GetDynamicWavesMapUV(refractedWorldPos, distanceToCamera);
float4 dynamicWavesRefracted = GetDynamicWavesMap(dynamicWavesMapUVRefracted);
float2 flowDirectionRefractedNormalized = NormalizeDynamicWavesVelocity(dynamicWavesRefracted.xy);
float velocityLengthRefracted = length(dynamicWavesRefracted.xy);
*/
float2 flowDirectionRefractedNormalized = flowDirectionNormalized;
float velocityLengthRefracted = velocityLength;
zoneCaustic = GetDynamicWavesZoneCaustic(causticUV, waterDepth, flowDirectionRefractedNormalized, velocityLengthRefracted, flowSpeedMultiplier, causticNoiseMask);
}
#endif
#if defined(KWS_USE_OCEAN_RENDERING)
if (zoneCausticFade < 0.95) oceanCaustic = GetOceanCaustic(i.pos.xy, causticUV, waterDepth);
#endif
float3 finalCaustic = lerp(oceanCaustic.xyz, zoneCaustic.xyz, zoneCausticFade);
float depthFadingDistance = saturate(waterDepth * 0.1);
finalCaustic *= lerp(saturate(1-saturate((distanceToCamera + 25) * 0.01) + 0.25), 1, saturate(depthFadingDistance));
#ifdef KWS_USE_VOLUMETRIC_LIGHT
VolumetricLightAdditionalData volumeData = GetVolumetricLightAdditionalData(screenUV);
finalCaustic *= KWS_Pow10(volumeData.SceneDirShadow);
#endif
refraction.rgb *= 1.0 + finalCaustic; // caustic ~ 0.01.0
#endif
///////////////////////////////////////////////////////////// end caustic ///////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// UNDERWATER ///////////////////////////////////////////////////////////////////
float2 refractedVolumeLightUV = lerp(refractionUV, screenUV, waterfallMask);
#if defined(KWS_USE_LOCAL_WATER_ZONES)
refractedVolumeLightUV = lerp(refractedVolumeLightUV, screenUV, localZoneDensity);
#endif
#ifdef KWS_USE_CUSTOM_MESH
refractedVolumeLightUV = screenUV;
#endif
float2 volumeDepth = GetWaterVolumeDepth(screenUV, surfaceDepthZ, refractedSceneZ, 0);
half4 volumeLight = GetVolumetricLightWithAbsorbtion(screenUV, refractedVolumeLightUV, 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;
float oceanFoam = 0;
float advectedFoam = 0;
float flowmapFoam = 0;
#if defined(KWS_USE_OCEAN_RENDERING)
UNITY_BRANCH
if(KWS_UseOceanFoam) //todo add KWS_UseOceanFoam keyword
{
float2 oceanUV = i.worldPos.xz * 0.05 * KWS_FoamTextureScaleMultiplier;
float2 dx = ddx(oceanUV);
float2 dy = ddy(oceanUV);
float4 oceanFoamTex = Tex2DStochastic(KW_FluidsFoamTex, sampler_KW_FluidsFoamTex, oceanUV, dx, dy).xyzw * (1-borderFade);
float4 foamChannelMask = saturate(1.0 - abs(KWS_FoamTextureType - float4(0, 1, 2, 3)));
float selectedFoamChannel = dot(oceanFoamTex, foamChannelMask);
oceanFoam = saturate(saturate(pow(selectedFoamChannel, KWS_FoamTextureContrast) - (1 - sqrt(foamMask))));
}
#endif
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES) || defined(KWS_USE_ZONE_INSTANCE)
UNITY_BRANCH
if (useDynamicWavesFoamTexture)
{
float foamTextureType = foamData.x;
float foamTextureContrast = foamData.y;
float2 foamTextureScale = foamData.zw;
float4 foamChannelMask = saturate(1.0 - abs(foamTextureType - float4(0, 1, 2, 3)));
UNITY_BRANCH
if (useAdvectedUV > 0)
{
float4 advectedFoam0 = KW_FluidsFoamTex.Sample(sampler_KW_FluidsFoamTex, advectedUV.xy * 20 * foamTextureScale);
float4 advectedFoam1 = KW_FluidsFoamTex.Sample(sampler_KW_FluidsFoamTex, advectedUV.zw * 20 * foamTextureScale);
float selectedFoamChannel0 = dot(advectedFoam0, foamChannelMask);
float selectedFoamChannel1 = dot(advectedFoam1, foamChannelMask);
float weight0 = sin(frac(KWS_ScaledTime / KWS_ADVECTED_UV_REPEAT_TIME) * 3.1415);
float weight1 = sin(frac((KWS_ScaledTime + KWS_ADVECTED_UV_REPEAT_TIME * 0.5) / KWS_ADVECTED_UV_REPEAT_TIME) * 3.1415);
weight0 = sqrt(weight0);
weight1 = sqrt(weight1);
advectedFoam = max(selectedFoamChannel0 * weight0, selectedFoamChannel1 * weight1) * borderFade;
advectedFoam = saturate(saturate(pow(advectedFoam, foamTextureContrast) - (1 - sqrt(foamMask))));
}
else
{
float flowSpeed = lerp(0.25, 0.5, riverMask);
float4 flowmapFoamTex = Texture2DSampleFlowmapJump(KW_FluidsFoamTex, sampler_KW_FluidsFoamTex, i.worldPos.xz * 0.05, flowDirectionNormalized * flowSpeed * 1.0, KWS_ScaledTime * 1 * flowSpeedMultiplier, foamTextureScale.x).xyzw * borderFade;
float selectedFoamChannel = dot(flowmapFoamTex, foamChannelMask);
flowmapFoam = saturate(saturate(pow(selectedFoamChannel, foamTextureContrast) - (1 - sqrt(foamMask))));
}
}
#endif
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES) || defined(KWS_USE_ZONE_INSTANCE) || defined(KWS_USE_OCEAN_RENDERING)
UNITY_BRANCH
if (useDynamicWavesFoamTexture || KWS_UseOceanFoam)
{
float3 surfaceColor = GetVolumetricSurfaceLight(screenUV);
float3 foamColor = 0;
foamColor += advectedFoam * dynamicWavesFoamAlpha;
foamColor += flowmapFoam * dynamicWavesFoamAlpha;
foamColor += oceanFoam;
foamColor += foamMask * 0.25 * KWS_TurbidityColor * borderFade * saturate(KWS_MAX_TRANSPARENT_INVERSE * transparent * 3);
foamColor = saturate(foamColor) * KWS_Pow3(alpha);
foamColor *= clamp(surfaceColor, 0, 1.15);
foamColor *= lerp(1, colorData.rgb, saturate(colorData.a * 1.35));
underwaterColor = lerp(underwaterColor + foamColor, foamColor, colorData.a);
}
#endif
float3 subsurfaceScatteringColor = ComputeSSS(screenUV, GetWaterSSS(screenUV), underwaterColor, volumeLight.a, transparent);
underwaterColor += subsurfaceScatteringColor * 5;
//return float4(underwaterColor.xyz, 1);
///////////////////////////////////////////////////////////// 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
#ifdef KWS_USE_PLANAR_REFLECTION
reflection = GetPlanarReflectionWithClipOffset(refl_uv) * exposure;
#else
#ifdef 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
#ifdef KWS_SSR_REFLECTION
float4 ssrReflection = GetScreenSpaceReflectionWithStretchingMask(refl_uv, i.worldPosRefracted);
float inverseReflectionFix = 1 - saturate(dot(reflDir, float3(0, 1, 0)));
inverseReflectionFix = lerp(1, KWS_Pow5(inverseReflectionFix), saturate((KWS_WindSpeed - 2.5) * 0.25));
inverseReflectionFix = lerp(inverseReflectionFix, 1, riverMask);
ssrReflection.a = lerp(0, ssrReflection.a, inverseReflectionFix);
reflection = lerp(reflection, ssrReflection.rgb, ssrReflection.a);
#endif
reflection *= surfaceMask * (1 - waterfallMask);
//reflection = ApplyShorelineWavesReflectionFix(reflDir, reflection, underwaterColor);
///////////////////////////////////////////////////////////// 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);
#ifdef 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 * saturate((1 - foamMask) * sunFadeFactor);
#endif
half3 fogColor;
half3 fogOpacity;
#ifdef KWS_HDRP
GetInternalFogVariables(i.pos, GetWorldSpaceViewDirNorm(i.worldPos), LinearEyeDepthUniversal(i.pos.z), i.worldPos, fogColor, fogOpacity);
#else
GetInternalFogVariables(LinearEyeDepthUniversal(i.pos.z), fogColor, fogOpacity);
#endif
finalColor.xyz = ComputeInternalFog(finalColor.xyz , fogColor, fogOpacity);
finalColor.xyz = ComputeThirdPartyFog(finalColor.xyz , i.worldPos, i.pos.xy / _ScreenParams.xy, i.pos.z);
finalColor += srpBatcherFix;
alpha *= saturate(waterDepth * 5);
return float4(finalColor, alpha);
}
struct WaterFragmentOutput
{
half4 pass1 : SV_Target0;
half2 pass2 : SV_Target1;
};
WaterFragmentOutput fragDepth(v2fDepth i, float facing : VFACE)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
WaterFragmentOutput o = (WaterFragmentOutput)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);
half surfaceMask = max(i.surfaceMask.x >= 0.999, i.surfaceMask.x <= 0.0001);
float distanceToCamera = GetWorldToCameraDistance(i.worldPos);
#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 (surfaceMask < 0.5)
{
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;
float shorelineMask = 1;
float riverMask = 0;
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES)
float3 dynamicWavesMapUV = GetDynamicWavesMapUV(i.worldPosRefracted, distanceToCamera);
isDynamicWavesZone = !IsOutsideUvBorders(dynamicWavesMapUV.xy);
if (isDynamicWavesZone)
{
float4 dynamicWaves = GetDynamicWavesMapBicubic(dynamicWavesMapUV);
DynamicWavesAdditionalData additionalData = GetDynamicWavesAdditionalMapBicubic(dynamicWavesMapUV);
dynamicWavesNormal = GetDynamicWavesNormalMap(dynamicWavesMapUV);
float waterfallThreshold = GetDynamicWavesWaterfallTreshold(dynamicWavesNormal);
dynamicWaves.xy = lerp(dynamicWaves.xy, dynamicWaves.xy * 0.2, waterfallThreshold);
borderFade = additionalData.zoneFade;
flowDirection = dynamicWaves.xy * borderFade;
shorelineMask = max(additionalData.shorelineMask, 1-borderFade);
velocityLength = length(dynamicWaves.xy) * borderFade;
ZoneData zone = KWS_ZoneData[additionalData.zoneID];
flowSpeedMultiplier = zone.flowSpeedMultiplier;
}
#endif
//float alpha = lerp(1-KWS_Pow5(1-borderFade), 1, KWS_RenderOcean);
//if (alpha < 0.001) discard;
float2 flowDirectionNormalized = NormalizeDynamicWavesVelocity(flowDirection);
///////////////////////////////////////////////////////////// NORMAL ////////////////////////////////////////////////////////////////////////////////////////////////////////
float3 tangentNormal = float3(0, 1, 0);
#if defined(KWS_USE_OCEAN_RENDERING)
float3 wavesNormalFoam = GetFftWavesNormalFoam(i.worldPos, i.windAttenuation);
tangentNormal = float3(wavesNormalFoam.x, 1, wavesNormalFoam.z);
tangentNormal = lerp(float3(0, 1, 0), tangentNormal, any(fwidth(i.worldPos.xz))); //fix horizontal flickering
#endif
float3 tangentNormalScatter = tangentNormal;
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES) || defined(KWS_USE_ZONE_INSTANCE)
if (isDynamicWavesZone && borderFade > 0.0)
{
riverMask = saturate(i.worldPosRefracted.y - KWS_WaterLevel - 3) * (1 - shorelineMask);
float3 dynamicWavesFlowNormal = Texture2DSampleFlowmapJump(KWS_WaterDynamicWavesFlowMapNormal, sampler_linear_repeat, i.worldPos.xz * 0.05, flowDirectionNormalized * 0.5, KWS_ScaledTime * 1.0 * flowSpeedMultiplier, 5).xzy * 2 - 1;
dynamicWavesFlowNormal.z *= -1;
dynamicWavesFlowNormal.xz *= RIVER_FLOW_NORMAL_MULTIPLIER * 0.5;
dynamicWavesFlowNormal = lerp(float3(0, 1, 0), dynamicWavesFlowNormal, riverMask * saturate(velocityLength - 0.15));
dynamicWavesNormal = KWS_BlendNormals(dynamicWavesNormal, dynamicWavesFlowNormal);
tangentNormal = lerp(KWS_BlendNormals(dynamicWavesNormal, tangentNormal), dynamicWavesNormal, saturate((1-shorelineMask) - 0.2));
}
#endif
//half surfaceMask = max(i.surfaceMask.x >= 0.999, i.surfaceMask.x <= 0.0001);
tangentNormal = lerp(float3(0, 1, 0), tangentNormal, surfaceMask);
float3 worldNormal = KWS_BlendNormals(tangentNormal, i.worldNormal);
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_USE_COLORED_DYNAMIC_WAVES)
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(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 && GetCameraAbsolutePosition().y > i.worldPos.y) discard;
}
#endif
float3 viewDir = GetWorldSpaceViewDirNorm(i.worldPosRefracted);
float3 lightDir = GetMainLightDir();
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