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

260 lines
8.1 KiB
HLSL

#ifndef KWS_WATER_VERT_PASS
#define KWS_WATER_VERT_PASS
struct waterInput
{
float4 vertex : POSITION;
float surfaceMask : COLOR0;
float3 normal : NORMAL;
#if defined(KWS_USE_WATER_INSTANCING)
float2 uvData : TEXCOORD0;
#endif
uint instanceID : SV_InstanceID;
};
struct v2fDepth
{
float4 pos : SV_POSITION;
float3 worldNormal : NORMAL;
float3 worldPos : TEXCOORD0;
float3 worldPosRefracted : TEXCOORD1;
float surfaceMask : COLOR0;
float windAttenuation : COLOR1;
float4 screenPos : TEXCOORD2;
float2 localHeightAndTensionMask : TEXCOORD32;
UNITY_VERTEX_OUTPUT_STEREO
};
struct v2fWater
{
float4 pos : SV_POSITION;
float3 worldNormal : NORMAL;
float surfaceMask : COLOR0;
float windAttenuation : COLOR1;
float3 worldPos : TEXCOORD0;
float3 worldPosRefracted : TEXCOORD1;
float4 screenPos : TEXCOORD2;
UNITY_VERTEX_OUTPUT_STEREO
};
struct WaterOffsetData
{
float3 offset;
float3 oceanOffset;
float foamMask;
float2 flowDirection;
float orthoDepth;
float windAttenuation;
float surfaceMask;
bool isRequireDiscardTriangle;
};
WaterOffsetData ComputeWaterOffset(float3 worldPos)
{
WaterOffsetData data = (WaterOffsetData)0;
data.windAttenuation = 1;
data.orthoDepth = -100000;
data.surfaceMask = 1;
float waterLevel = 0;
float terrainLevel = 0;
float shorelineMask = 1;
#if defined(KWS_USE_LOCAL_WATER_ZONES)
uint zoneIndexOffset_local = 0;
uint zoneIndexCount_local = 0;
bool isLocalWaterZone = GetTileRange_LocalZone(worldPos, zoneIndexOffset_local, zoneIndexCount_local);
if (isLocalWaterZone)
{
float offsetBlending = 0;
float maxHeightOffset = -100000;
for (uint zoneIndex = zoneIndexOffset_local; zoneIndex < zoneIndexCount_local; zoneIndex++)
{
LocalZoneData zone = (LocalZoneData)0;
if (GetWaterZone_LocalZone(worldPos, zoneIndex, zone))
{
if (zone.overrideWindSettings > 0.5)
{
float zoneFade = GetLocalWaterZoneSphereBlendFactor(zone.uv, saturate(zone.windEdgeBlending + 0.25));
data.windAttenuation = lerp(lerp(data.windAttenuation, zone.windStrengthMultiplier, zoneFade), zone.windStrengthMultiplier, KWS_Pow10(zone.windEdgeBlending));
}
if (zone.overrideHeight > 0.5)
{
float currentHeightOffset = zone.center.y + zone.halfSize.y - KWS_WaterPosition.y;
float heightFade = GetLocalWaterZoneSphereBlendFactor(zone.uv, zone.heightEdgeBlending);
maxHeightOffset = max(maxHeightOffset, currentHeightOffset);
offsetBlending = lerp(heightFade, 1, KWS_Pow20(zone.heightEdgeBlending));
data.surfaceMask = 0;
}
}
}
data.offset.y += lerp(0, maxHeightOffset, offsetBlending);
}
#endif
float3 disp = 0;
#if defined(KWS_USE_LOCAL_WATER_ZONES)
disp = GetFftWavesDisplacementWithAttenuation(worldPos, data.windAttenuation);
#else
disp = GetFftWavesDisplacement(worldPos);
#endif
data.oceanOffset = disp;
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
bool isOutDistance = GetWorldToCameraDistance(worldPos) > KW_WaterFarDistance * 0.5 - Test4.x;
if (!isOutDistance)
{
#endif
#if defined(KWS_USE_DYNAMIC_WAVES)
uint zoneIndexOffset = 0;
uint zoneIndexCount = 0;
if (GetTileRange(worldPos, zoneIndexOffset, zoneIndexCount))
{
for (uint zoneIndex = zoneIndexOffset; zoneIndex < zoneIndexCount; zoneIndex++)
{
ZoneData zone = (ZoneData)0;
if (GetWaterZone(worldPos, zoneIndex, zone))
{
float4 dynamicWaves = GetDynamicWavesZoneBicubic(zone.id, zone.uv);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalData(zone.id, zone.uv);
float zoneFade = GetDynamicWavesBorderFading(zone.uv);
float zoneDepthMask = GetDynamicWavesZoneDepthMask(zone.id, zone.uv);
waterLevel = max(waterLevel, dynamicWaves.z * zoneFade);
terrainLevel = max(terrainLevel, dynamicWaves.w);
data.flowDirection = data.flowDirection + NormalizeDynamicWavesVelocity(dynamicWaves.xy);
shorelineMask = (shorelineMask * dynamicWavesAdditionalData.y);
data.foamMask = max(data.foamMask, dynamicWavesAdditionalData.z * zoneFade);
data.orthoDepth = max(data.orthoDepth, zoneDepthMask > 0.0 ? zoneDepthMask : - 100000);
// if ((waterLevel + terrainLevel) <= 0.0001 && shorelineMask <= 0.0001) data.isRequireDiscardTriangle = true;
//data.surfaceMask = terrainLevel > waterLevel ? 0 : 1;
}
}
}
#endif
#if defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
float2 movableZoneUV = 0;
if (GetWaterZoneMovable(worldPos, movableZoneUV))
{
float4 dynamicWaves = GetDynamicWavesZoneMovable(movableZoneUV);
float4 dynamicWavesAdditionalData = GetDynamicWavesZoneAdditionalDataMovable(movableZoneUV); //(wetmap, shoreline mask, foam mask, wetDepth)
float zoneFade = GetDynamicWavesBorderFading(movableZoneUV);
float zoneDepthMask = GetDynamicWavesZoneDepthMaskMovable(movableZoneUV);
waterLevel = max(waterLevel, dynamicWaves.z * zoneFade);
terrainLevel = max(terrainLevel, dynamicWaves.w);
data.flowDirection = data.flowDirection + NormalizeDynamicWavesVelocity(dynamicWaves.xy);
shorelineMask = (shorelineMask * dynamicWavesAdditionalData.y);
data.foamMask = max(data.foamMask, dynamicWavesAdditionalData.z * zoneFade);
data.orthoDepth = max(data.orthoDepth, zoneDepthMask > 0.0 ? zoneDepthMask : - 100000);
}
#endif
#if defined(KWS_USE_DYNAMIC_WAVES) || defined(KWS_DYNAMIC_WAVES_USE_MOVABLE_ZONE)
//waterLevel = lerp(waterLevel, waterLevel * 0.1, saturate(pow(waterLevel * 0.3, 0.1) * (pow(1 - shorelineMask, 15))));
disp *= shorelineMask;
disp.y += waterLevel + terrainLevel;
//disp.xz += data.flowDirection * max(0.5, waterLevel) * KWS_DYNAMIC_WAVES_MAX_XZ_OFFSET * lerp(7, 2, 1-KWS_Pow2(1-shorelineMask));
disp.xz += data.flowDirection * lerp(1, 3, saturate(waterLevel * waterLevel)) * KWS_DYNAMIC_WAVES_MAX_XZ_OFFSET;
}
#endif
data.offset += disp;
data.offset.y += KWS_OceanLevelHeightOffset;
return data;
}
v2fDepth vertDepth(waterInput v)
{
v2fDepth o = (v2fDepth)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
KWS_INITIALIZE_DEFAULT_MATRIXES;
#if defined(KWS_USE_WATER_INSTANCING) && !defined(USE_WATER_TESSELATION)
UpdateInstanceData(v.instanceID, v.uvData, v.vertex, KWS_MATRIX_M, KWS_MATRIX_I_M);
#endif
o.worldPos.xyz = LocalToWorldPos(v.vertex.xyz, KWS_MATRIX_M);
WaterOffsetData offsetData = ComputeWaterOffset(o.worldPos.xyz);
float3 offset = WorldToLocalPosWithoutTranslation(offsetData.offset, KWS_MATRIX_I_M);
// if (offsetData.isRequireDiscardTriangle)
// {
// o.pos.w = NAN_VALUE;
// return o;
// }
v.vertex.xyz += offset;
o.surfaceMask = v.surfaceMask* offsetData.surfaceMask;
o.windAttenuation = offsetData.windAttenuation;
o.worldPosRefracted.xyz = LocalToWorldPos(v.vertex.xyz, KWS_MATRIX_M);
o.localHeightAndTensionMask.x = offset.y;
o.localHeightAndTensionMask.y = v.vertex.y - offset.y;
o.pos = ObjectToClipPos(v.vertex, KWS_MATRIX_M, KWS_MATRIX_I_M);
o.screenPos = ComputeScreenPos(o.pos);
o.worldNormal = GetWorldSpaceNormal(v.normal, KWS_MATRIX_M);
return o;
}
v2fWater vertWater(waterInput v)
{
v2fWater o = (v2fWater)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
KWS_INITIALIZE_DEFAULT_MATRIXES;
#if defined(KWS_USE_WATER_INSTANCING) && !defined(USE_WATER_TESSELATION)
UpdateInstanceData(v.instanceID, v.uvData, v.vertex, KWS_MATRIX_M, KWS_MATRIX_I_M);
#endif
o.worldPos = LocalToWorldPos(v.vertex.xyz, KWS_MATRIX_M);
WaterOffsetData offsetData = ComputeWaterOffset(o.worldPos.xyz);
float3 offset = WorldToLocalPosWithoutTranslation(offsetData.offset, KWS_MATRIX_I_M);
//
// if (offsetData.isRequireDiscardTriangle)
// {
// o.pos.w = NAN_VALUE;
// return o;
// }
v.vertex.xyz += offset;
o.surfaceMask = v.surfaceMask * offsetData.surfaceMask;
o.windAttenuation = offsetData.windAttenuation;
o.worldPosRefracted = LocalToWorldPos(v.vertex.xyz, KWS_MATRIX_M);
o.pos = ObjectToClipPos(v.vertex, KWS_MATRIX_M, KWS_MATRIX_I_M);
o.screenPos = ComputeScreenPos(o.pos);
o.worldNormal = GetWorldSpaceNormal(v.normal, KWS_MATRIX_M);
return o;
}
#endif