588 lines
23 KiB
HLSL
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 |