|
@@ -1,237 +0,0 @@
|
|
|
-//Structs
|
|
|
|
|
-struct Complex{
|
|
|
|
|
- x: f32,
|
|
|
|
|
- y:f32
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-struct SpectrumParameters {
|
|
|
|
|
- scale: f32,
|
|
|
|
|
- angle: f32,
|
|
|
|
|
- spreadBlend: f32,
|
|
|
|
|
- swell: f32,
|
|
|
|
|
- alpha: f32,
|
|
|
|
|
- peakOmega: f32,
|
|
|
|
|
- gamma: f32,
|
|
|
|
|
- shortWavesFade: f32,
|
|
|
|
|
-};
|
|
|
|
|
-//Constants
|
|
|
|
|
-let PI: f32 = 3.14159265358979323846;
|
|
|
|
|
-let GRAVITY = 9.81;
|
|
|
|
|
-let DEPTH = 20;
|
|
|
|
|
-let N = 5;
|
|
|
|
|
-let SEED = 325235235;
|
|
|
|
|
-let LENGTHSCALE0 = 1;
|
|
|
|
|
-let LENGTHSCALE1 = 1;
|
|
|
|
|
-let LENGTHSCALE2 = 1;
|
|
|
|
|
-let LENGTHSCALE3 = 1;
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-fn add_complex(a:Complex, b:Complex)-> Complex{
|
|
|
|
|
- return Complex(
|
|
|
|
|
- a.x + b.x,
|
|
|
|
|
- a.y + b.y
|
|
|
|
|
- )
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn multiply_complex(a:Complex, b:Complex)-> Complex{
|
|
|
|
|
- return Complex(
|
|
|
|
|
- (a.x * b.x) - (a.y * b.y),
|
|
|
|
|
- (a.x * b.y) + (b.x * a.y)
|
|
|
|
|
- )
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn gaussian(x: f32, y:f32)-> f32{
|
|
|
|
|
- //Mean = 0
|
|
|
|
|
- let spread = 1.0;
|
|
|
|
|
- let sigma_squared = spread * spread;
|
|
|
|
|
- return (1 / (sqrt(2 * PI)* spread)) * exp(-((x * x) + (y * y)) / (2 * sigmaSqu));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn angle_to_complex(x:f32)-> Complex{
|
|
|
|
|
- return Complex(
|
|
|
|
|
- cos(x),
|
|
|
|
|
- sin(x)
|
|
|
|
|
- )
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// fn hash(n: u32) -> f32 {
|
|
|
|
|
-// let mut n = (n << 13u);
|
|
|
|
|
-// n1 ^= n1;
|
|
|
|
|
-// n = n * (n * n * 15731u + 0x789221u) + 0x1376312589u;
|
|
|
|
|
-// return f32(n & 0x7fffffffu) / 0.7976709; // 0x7fffffff is the same as 2^31 - 1
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-fn UniformToGaussian(u1: f32, u2: f32) -> vec2<f32> {
|
|
|
|
|
- // Calculate the radius (R) from the first uniform value
|
|
|
|
|
- let R = sqrt(-2.0 * log(max(u1, 0.00001))); // Clamp u1 to avoid log(0)
|
|
|
|
|
-
|
|
|
|
|
- // Calculate the angle (theta) from the second uniform value
|
|
|
|
|
- let theta = 2.0 * PI * u2;
|
|
|
|
|
-
|
|
|
|
|
- // Return a 2D vector with R * cos(theta) and R * sin(theta)
|
|
|
|
|
- return vec2<f32>(R * cos(theta), R * sin(theta));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn Dispersion(kMag: f32) -> f32 {
|
|
|
|
|
- let depth = constant _Depth; // Assuming _Depth is a constant
|
|
|
|
|
- return sqrt(GRAVITY * kMag * tanh(min(kMag * depth, 20.0)));
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn DispersionDerivative(kMag: f32) -> f32 {
|
|
|
|
|
- let th = tanh(min(kMag * constant _Depth, 20.0)); // Assuming _Depth is a constant
|
|
|
|
|
- let ch = cosh(kMag * constant _Depth); // Assuming _Depth is a constant
|
|
|
|
|
- return GRAVITY * (depth * kMag / ch / ch + th) / Dispersion(kMag) / 2.0;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn NormalizationFactor(s: f32) -> f32 {
|
|
|
|
|
- let s2 = s * s;
|
|
|
|
|
- let s3 = s2 * s;
|
|
|
|
|
- let s4 = s3 * s;
|
|
|
|
|
- let threshold = 5.0;
|
|
|
|
|
- return if s < threshold {
|
|
|
|
|
- -0.000564 * s4 + 0.00776 * s3 - 0.044 * s2 + 0.192 * s + 0.163
|
|
|
|
|
- } else {
|
|
|
|
|
- -4.80e-08 * s4 + 1.07e-05 * s3 - 9.53e-04 * s2 + 5.90e-02 * s + 3.93e-01
|
|
|
|
|
- };
|
|
|
|
|
-}
|
|
|
|
|
-fn DonelanBannerBeta(x: f32) -> f32 {
|
|
|
|
|
- let threshold1 = 0.95;
|
|
|
|
|
- let threshold2 = 1.6;
|
|
|
|
|
- let factor1 = 2.61;
|
|
|
|
|
- let factor2 = 2.28;
|
|
|
|
|
- let power1 = 1.3;
|
|
|
|
|
- let power2 = -1.3;
|
|
|
|
|
-
|
|
|
|
|
- if x < threshold1 {
|
|
|
|
|
- return factor1 * abs(x) ^ power1;
|
|
|
|
|
- } else if x < threshold2 {
|
|
|
|
|
- return factor2 * abs(x) ^ power2;
|
|
|
|
|
- } else {
|
|
|
|
|
- let p = -0.4 + 0.8393 * exp(-0.567 * log(x * x));
|
|
|
|
|
- return pow(10.0, p);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn DonelanBanner(theta: f32, omega: f32, peakOmega: f32) -> f32 {
|
|
|
|
|
- let beta = DonelanBannerBeta(omega / peakOmega);
|
|
|
|
|
- let sech = 1.0 / cosh(beta * theta);
|
|
|
|
|
- return beta / 2.0 / tanh(3.14159 * beta) * sech * sech;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn Cosine2s(theta: f32, s: f32) -> f32 {
|
|
|
|
|
- return NormalizationFactor(s) * pow(abs(cos(0.5 * theta)), 2.0 * s);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn SpreadPower(omega: f32, peakOmega: f32) -> f32 {
|
|
|
|
|
- let threshold = peakOmega;
|
|
|
|
|
- let factor1 = 9.77;
|
|
|
|
|
- let factor2 = 6.97;
|
|
|
|
|
- let power1 = -2.5;
|
|
|
|
|
- let power2 = 5.0;
|
|
|
|
|
-
|
|
|
|
|
- if omega > threshold {
|
|
|
|
|
- return factor1 * abs(omega / peakOmega) ^ power1;
|
|
|
|
|
- } else {
|
|
|
|
|
- return factor2 * abs(omega / peakOmega) ^ power2;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-fn DirectionSpectrum(theta: f32, omega: f32, spectrum: SpectrumParameters) -> f32 {
|
|
|
|
|
- let peakOmega = spectrum.peakOmega;
|
|
|
|
|
- let swell = spectrum.swell;
|
|
|
|
|
- let spreadBlend = spectrum.spreadBlend;
|
|
|
|
|
- let s = SpreadPower(omega, peakOmega) + 16.0 * tanh(min(omega / peakOmega, 20.0)) * swell * swell;
|
|
|
|
|
- return lerp(2.0 / 3.14159 * cos(theta) * cos(theta), Cosine2s(theta - spectrum.angle, s), spreadBlend);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn TMACorrection(omega: f32) -> f32 {
|
|
|
|
|
- let depth = constant _Depth; // Assuming _Depth is a constant
|
|
|
|
|
- let omegaH = omega * sqrt(depth / GRAVITY);
|
|
|
|
|
-
|
|
|
|
|
- if omegaH <= 1.0 {
|
|
|
|
|
- return 0.5 * omegaH * omegaH;
|
|
|
|
|
- } else if omegaH < 2.0 {
|
|
|
|
|
- return 1.0 - 0.5 * (2.0 - omegaH) * (2.0 - omegaH);
|
|
|
|
|
- } else {
|
|
|
|
|
- return 1.0;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn JONSWAP(omega: f32, spectrum: SpectrumParameters) -> f32 {
|
|
|
|
|
- let peakOmega = spectrum.peakOmega;
|
|
|
|
|
- let sigma = if omega <= peakOmega { 0.07 } else { 0.09 };
|
|
|
|
|
- let r = exp(-(omega - peakOmega) * (omega - peakOmega) / 2.0 / sigma / sigma / peakOmega / peakOmega);
|
|
|
|
|
- let oneOverOmega = 1.0 / omega;
|
|
|
|
|
- let peakOmegaOverOmega = peakOmega / omega;
|
|
|
|
|
- return spectrum.scale * TMACorrection(omega) * spectrum.alpha * GRAVITY * GRAVITY *
|
|
|
|
|
- oneOverOmega * oneOverOmega * oneOverOmega * oneOverOmega * oneOverOmega *
|
|
|
|
|
- exp(-1.25 * peakOmegaOverOmega * peakOmegaOverOmega * peakOmegaOverOmega * peakOmegaOverOmega) *
|
|
|
|
|
- pow(abs(spectrum.gamma), r);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-fn ShortWavesFade(kLength: f32, spectrum: SpectrumParameters) -> f32 {
|
|
|
|
|
- return exp(-spectrum.shortWavesFade * spectrum.shortWavesFade * kLength * kLength);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// fn CS_InitializeSpectrum(id: u32) {
|
|
|
|
|
-// // Seed generation based on thread ID
|
|
|
|
|
-// let seed = u32(id.x) + N * u32(id.y) + N;
|
|
|
|
|
-// seed += SEED;
|
|
|
|
|
-
|
|
|
|
|
-// // Pre-defined length scales
|
|
|
|
|
-// let lengthScales: array<f32, 4> = [LENGTHSCALE0, LENGTHSCALE1, LENGTHSCALE2, LENGTHSCALE3];
|
|
|
|
|
-
|
|
|
|
|
-// // Loop through all scales
|
|
|
|
|
-// for (let i: u32 = 0; i < 4; i++) {
|
|
|
|
|
-// let halfN = N / 2.0;
|
|
|
|
|
-// let deltaK = 2.0 * PI / lengthScales[i];
|
|
|
|
|
-// let K = vec2<f32>(f32(id.x) - halfN, f32(id.y) - halfN) * deltaK;
|
|
|
|
|
-// let kLength = length(K);
|
|
|
|
|
-
|
|
|
|
|
-// // Update seed with scrambling
|
|
|
|
|
-// seed += i + hash(seed) * 10.0;
|
|
|
|
|
-// let uniformRandSamples = vec4<f32>(hash(seed), hash(seed * 2.0), hash(seed * 3.0), hash(seed * 4.0));
|
|
|
|
|
-// let gauss1 = UniformToGaussian(uniformRandSamples.x, uniformRandSamples.y);
|
|
|
|
|
-// let gauss2 = UniformToGaussian(uniformRandSamples.z, uniformRandSamples.w);
|
|
|
|
|
-
|
|
|
|
|
-// // Check if wave number is within cut-off range
|
|
|
|
|
-// if (_LowCutoff <= kLength && kLength <= _HighCutoff) {
|
|
|
|
|
-// let kAngle = atan2(K.y, K.x);
|
|
|
|
|
-// let omega = Dispersion(kLength);
|
|
|
|
|
-// let dOmegadk = DispersionDerivative(kLength);
|
|
|
|
|
-
|
|
|
|
|
-// // Calculate spectrum for this wave number and scale
|
|
|
|
|
-// let spectrum = JONSWAP(omega, _Spectrums[i * 2]) * DirectionSpectrum(kAngle, omega, _Spectrums[i * 2]) * ShortWavesFade(kLength, _Spectrums[i * 2]);
|
|
|
|
|
-
|
|
|
|
|
-// // Add contribution from secondary spectrum if present
|
|
|
|
|
-// if (_Spectrums[i * 2 + 1].scale > 0.0) {
|
|
|
|
|
-// spectrum += JONSWAP(omega, _Spectrums[i * 2 + 1]) * DirectionSpectrum(kAngle, omega, _Spectrums[i * 2 + 1]) * ShortWavesFade(kLength, _Spectrums[i * 2 + 1]);
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// // Fill initial spectrum texture with calculated values
|
|
|
|
|
-// _InitialSpectrumTextures[u32(id.xy, i)] = vec4(vec2(gauss2.x, gauss1.y) * sqrt(2.0 * spectrum * abs(dOmegadk) / kLength * deltaK * deltaK), 0.0, 0.0);
|
|
|
|
|
-// } else {
|
|
|
|
|
-// // Set to zero if wave number is outside cut-off range
|
|
|
|
|
-// _InitialSpectrumTextures[u32(id.xy, i)] = vec4(0.0);
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-fn CS_PackSpectrumConjugate(id: u32) {
|
|
|
|
|
- // Loop through all scales
|
|
|
|
|
- for (let i: u32 = 0; i < 4; i++) {
|
|
|
|
|
- // Access initial spectrum data (assuming vec2 for real and imaginary parts)
|
|
|
|
|
- let h0 = vec2(_InitialSpectrumTextures[u32(id.xy, i)].x, _InitialSpectrumTextures[u32(id.xy, i)].y);
|
|
|
|
|
-
|
|
|
|
|
- // Calculate mirrored thread ID for conjugate access
|
|
|
|
|
- let mirrored_id = u32(N - id.x % N, N - id.y % N, i);
|
|
|
|
|
-
|
|
|
|
|
- // Access conjugate spectrum data
|
|
|
|
|
- let h0conj = vec2(_InitialSpectrumTextures[mirrored_id].x, -_InitialSpectrumTextures[mirrored_id].y);
|
|
|
|
|
-
|
|
|
|
|
- // Pack spectrum and conjugate into a vec4
|
|
|
|
|
- _InitialSpectrumTextures[u32(id.xy, i)] = vec4(h0, h0conj.x, -h0conj.y);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|