Files
Fishing2/Packages/com.waveharmonic.crest/Runtime/Shaders/Data/Query/Query.compute
2026-01-01 22:00:33 +08:00

103 lines
3.7 KiB
Plaintext

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#pragma kernel CrestQueryDisplacement d_CrestDisplacement
#pragma kernel CrestQueryFlow d_CrestFlow
#pragma kernel CrestQueryDepth d_CrestDepth
// Must match value in script.
#define GROUP_SIZE 64
StructuredBuffer<float3> _Crest_QueryPositions_MinimumGridSizes;
RWStructuredBuffer<float3> _Crest_Target;
#include "HLSLSupport.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
#if d_CrestDisplacement
#define d_CrestSample SampleDisplacement
#define d_CrestMake MakeAnimatedWaves
#define d_CrestComponents float3
#define d_CrestReturn result
#elif d_CrestDepth
#define d_CrestSample SampleSignedDepthFromSeaLevelAndDistance
#define d_CrestMake MakeDepth
#define d_CrestComponents float2
#define d_CrestReturn float3(result.x, result.y, 0.0)
#else
#define d_CrestSample SampleFlow
#define d_CrestMake MakeFlow
#define d_CrestComponents float2
// Unfortunately we don't support float2 vs float3s yet, on the C# side
#define d_CrestReturn float3(result.x, 0.0, result.y)
#endif
m_CrestNameSpace
float3 Compute(const float2 i_Position, const float i_MinimumSlice, const float i_BaseScale)
{
// Do not use last slice - this is a 'transition' slice used to cross-fade waves
// between LOD resolutions to avoid pops. That being said, this will have clamped
// samples leading to objects floating on waves that do not exist.
uint slice0, slice1; float alpha;
PosToSliceIndices(i_Position, i_MinimumSlice, g_Crest_LodCount - 2.0, i_BaseScale, slice0, slice1, alpha);
const Cascade cascade0 = Cascade::d_CrestMake(slice0);
const Cascade cascade1 = Cascade::d_CrestMake(slice1);
const float weight0 = (1.0 - alpha) * Cascade::Make(slice0)._Weight;
const float weight1 = (1.0 - weight0) * Cascade::Make(slice1)._Weight;
d_CrestComponents result =
weight0 * cascade0.d_CrestSample(i_Position) +
weight1 * cascade1.d_CrestSample(i_Position);
return d_CrestReturn;
}
void Query(const uint3 id)
{
const float3 data = _Crest_QueryPositions_MinimumGridSizes[id.x];
const float minimumGridSize = data.z;
float2 position = data.xy;
const float gridSizeSlice0 = Cascade::d_CrestMake(0)._Texel;
// Displacements should not utilize the last slice which is used for transitioning
// waves between sampling resolutions. While it might be ok to use the last slice
// for other targets, we avoid using it to be consistent with displacements.
const float minimumSlice = clamp(floor(log2(max(minimumGridSize / gridSizeSlice0, 1.0))), 0.0, g_Crest_LodCount - 2.0);
#if d_CrestDisplacement
// Perform iteration to invert the displacement vector field - find position that displaces to query position,
// and return displacement at that point.
float2 undisplaced = position;
for (int i = 0; i < 4; i++)
{
const float3 displacement = Compute(undisplaced, minimumSlice, g_Crest_WaterScale);
const float2 error = (undisplaced + displacement.xz) - position;
undisplaced -= error;
}
position = undisplaced;
#endif
_Crest_Target[id.x] = Compute(position, minimumSlice, g_Crest_WaterScale);
}
m_CrestNameSpaceEnd
[numthreads(GROUP_SIZE, 1, 1)]
m_CrestKernelVariant(Query, Displacement)
[numthreads(GROUP_SIZE, 1, 1)]
m_CrestKernelVariant(Query, Flow)
[numthreads(GROUP_SIZE, 1, 1)]
m_CrestKernelVariant(Query, Depth)