This commit is contained in:
Andras Schmelczer 2026-05-21 07:43:10 +01:00
parent 2fe3c69963
commit 6bc125be1c
104 changed files with 3088 additions and 2414 deletions

View file

@ -11,9 +11,13 @@ struct Settings {
const WORKGROUP_SIZE_X = 16u;
const WORKGROUP_SIZE_Y = 16u;
// One-pixel halo on each side so the 3x3 neighbourhood read in the main pass
// can be served from workgroup memory without bounds checks for interior tiles.
const TILE_SIZE_X = WORKGROUP_SIZE_X + 2u;
const TILE_SIZE_Y = WORKGROUP_SIZE_Y + 2u;
const TILE_TEXEL_COUNT = TILE_SIZE_X * TILE_SIZE_Y;
// 1.0 / 2^32, used to map a 32-bit hash to [0, 1).
const HASH_TO_UNIT_FLOAT: f32 = 2.3283064365386963e-10;
@group(0) @binding(0) var<uniform> settings: Settings;
@group(0) @binding(1) var trailMap: texture_2d<f32>;
@ -62,16 +66,8 @@ fn main(
let centerTileIndex = centerTilePosition.y * TILE_SIZE_X + centerTilePosition.x;
var current = tile[centerTileIndex];
let random = random_from_pixel(pixel);
let r2 = random * random;
let r4 = r2 * r2;
let r8 = r4 * r4;
let r16 = r8 * r8;
let trailWeight = diffusion_weight(
random,
r2,
r4,
r8,
r16,
settings.inverseDiffusionRateTrails
);
current += (
@ -118,15 +114,13 @@ fn random_from_pixel(pixel: vec2<i32>) -> f32 {
hash = (hash ^ (hash >> 16u)) * 2246822519u;
hash = (hash ^ (hash >> 13u)) * 3266489917u;
hash = hash ^ (hash >> 16u);
return f32(hash) * 2.3283064365386963e-10;
return f32(hash) * HASH_TO_UNIT_FLOAT;
}
// Approximates pow(r, inverseRate) piecewise between powers (r, r^2, r^4, r^8, r^16)
// so we can vary diffusion sharpness without paying for a real pow() per pixel.
fn diffusion_weight(
r: f32,
r2: f32,
r4: f32,
r8: f32,
r16: f32,
inverseRate: f32
) -> f32 {
if inverseRate < 1.0 {
@ -137,19 +131,22 @@ fn diffusion_weight(
clamp((inverseRate - 0.5) * 2.0, 0.0, 1.0)
);
}
let r2 = r * r;
if inverseRate < 2.0 {
return mix(r, r2, inverseRate - 1.0);
}
let r4 = r2 * r2;
if inverseRate < 4.0 {
// (inverseRate - 2.0) / (4.0 - 2.0)
return mix(r2, r4, (inverseRate - 2.0) * 0.5);
}
let r8 = r4 * r4;
if inverseRate < 8.0 {
// (inverseRate - 4.0) / (8.0 - 4.0)
return mix(r4, r8, (inverseRate - 4.0) * 0.25);
}
let r16 = r8 * r8;
// (inverseRate - 8.0) / (16.0 - 8.0); past 16, falls off as 16/inverseRate.
return mix(r8, r16, clamp((inverseRate - 8.0) * 0.125, 0.0, 1.0))
* min(1.0, 16.0 / inverseRate);
}