Files
2026-03-05 00:14:42 +08:00

98 lines
2.4 KiB
Plaintext

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#pragma kernel CrestExecute
#pragma multi_compile_local d_Sphere d_Cube d_Rectangle
#pragma multi_compile_local __ d_Inverted
#include "HLSLSupport.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
RWTexture2DArray<float1> _Crest_Target;
CBUFFER_START(CrestPerMaterial)
float3 _Crest_Position;
float _Crest_Diameter;
float4x4 _Crest_Matrix;
CBUFFER_END
m_CrestNameSpace
// Also covers elipsoids etc.
float SphereSDF(float3 position)
{
// Distance from center.
return length(position);
}
// Also covers rectangular prisms etc.
float CubeSDF(float3 position)
{
// Restrict to one quadrant of a box.
position = abs(position);
// Get furthest distance from center.
return max(position.x, max(position.y, position.z));
}
float RectangleSDF(float2 position)
{
// Restrict to one quadrant of a box.
position = abs(position);
// Get furthest distance from center.
return max(position.x, position.y);
}
void Execute(uint3 id)
{
const Cascade cascade = Cascade::MakeClip(id.z);
const float2 positionXZ = cascade.IDToWorld(id.xy);
// TODO: Optimize with something better than spherical culling.
// Spherical culling. Check diameter for buffered area.
if (length(positionXZ - _Crest_Position.xz) > _Crest_Diameter)
{
return;
}
float3 position = 0.0;
position.xz = positionXZ;
#if !d_Rectangle
// Only need height as clip surface is sampled at the displaced position.
const float3 surface = Cascade::MakeAnimatedWaves(id.z).SampleDisplacementFromUndisplaced(positionXZ);
position.y = g_Crest_WaterCenter.y + surface.y;
#endif
// SDF operate in local space.
position = mul(_Crest_Matrix, float4(position, 1.0)).xyz;
float sdf = 0;
#if d_Sphere
sdf = SphereSDF(position);
#endif
#if d_Cube
sdf = CubeSDF(position);
#endif
#if d_Rectangle
sdf = RectangleSDF(position.xz);
#endif
#if d_Inverted
_Crest_Target[id.xyz] = min(_Crest_Target[id.xyz], sdf);
#else
sdf = 1.0 - sdf;
_Crest_Target[id.xyz] = max(_Crest_Target[id.xyz], sdf);
#endif
}
m_CrestNameSpaceEnd
m_CrestInputKernelDefault(Execute)