260 lines
8.1 KiB
HLSL
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 |