diff --git a/THIRD-PARTY-NOTICES.md b/THIRD-PARTY-NOTICES.md index c897620..8339c5f 100644 --- a/THIRD-PARTY-NOTICES.md +++ b/THIRD-PARTY-NOTICES.md @@ -15,7 +15,10 @@ Rune Skovbo Johansen's **Advanced Terrain Erosion Filter**: The CultMath files retain the MPL notice and separate the faithful planar filter from CultMath's spherical adaptation. Modifications include C#/HLSL type lowering, explicit bounded octave counts, finite zero-rounding behavior, -and CultMath naming. +and CultMath naming. CultMath replaces the reference floating hash with a +shared integer avalanche hash so C# and GPU evaluation select identical cell +pivots across devices; this changes the stochastic pattern, not the filter +mechanics. The technique builds on earlier work credited by the upstream author to Fewes and Clay John. The hash form follows the public shader math of Inigo Quilez. diff --git a/shaders/AdvancedErosionFilter.hlsl b/shaders/AdvancedErosionFilter.hlsl index 6c35dd4..38c3ef1 100644 --- a/shaders/AdvancedErosionFilter.hlsl +++ b/shaders/AdvancedErosionFilter.hlsl @@ -19,11 +19,16 @@ struct CultMathAdvancedErosionResult float3 delta; float magnitude; float ridge_map; float fade_target; }; +float cultmath_erosion_hash_unit(int2 cell, uint salt) +{ + uint value = (uint)cell.x * 0x8da6b343u ^ (uint)cell.y * 0xd8163841u ^ salt; + value ^= value >> 16; value *= 0x7feb352du; value ^= value >> 15; value *= 0x846ca68bu; value ^= value >> 16; + return (value & 0x00ffffffu) * (1.0 / 16777216.0); +} float2 cultmath_erosion_hash2(float2 input) { - float2 k = float2(0.3183099, 0.3678794); - float2 x = input * k + k.yx; - return -1.0 + 2.0 * frac(16.0 * k * frac(x.x * x.y * (x.x + x.y))); + int2 cell = (int2)input; + return float2(cultmath_erosion_hash_unit(cell, 0x68bc21ebu), cultmath_erosion_hash_unit(cell, 0x02e5be93u)) * 2.0 - 1.0; } float4 cultmath_phacelle_noise(float2 position, float2 normal_direction, float frequency, float offset_cycles, float normalization) diff --git a/src/CultMath/AdvancedErosionFilter.cs b/src/CultMath/AdvancedErosionFilter.cs index f004c32..6780223 100644 --- a/src/CultMath/AdvancedErosionFilter.cs +++ b/src/CultMath/AdvancedErosionFilter.cs @@ -109,10 +109,16 @@ public static class AdvancedErosionFilter private static float2 Hash2(float2 input) { - var k = new float2(0.3183099f, 0.3678794f); - var x = input * k + new float2(k.y, k.x); - var scalar = math.frac(x.x * x.y * (x.x + x.y)); - return -float2.one + 2.0f * math.frac(16.0f * k * scalar); + var x = (int)input.x; + var y = (int)input.y; + return new float2(HashUnit(x, y, 0x68bc21ebu), HashUnit(x, y, 0x02e5be93u)) * 2.0f - float2.one; + } + + private static float HashUnit(int x, int y, uint salt) + { + var value = unchecked((uint)x * 0x8da6b343u ^ (uint)y * 0xd8163841u ^ salt); + value ^= value >> 16; value *= 0x7feb352du; value ^= value >> 15; value *= 0x846ca68bu; value ^= value >> 16; + return (value & 0x00ffffffu) * (1.0f / 16777216.0f); } private static float2 SafeNormalize(float2 value)