diff --git a/crates/horizon-client/src/gfx/hd/smoke.rs b/crates/horizon-client/src/gfx/hd/smoke.rs index dee0932e8..c751df4f4 100644 --- a/crates/horizon-client/src/gfx/hd/smoke.rs +++ b/crates/horizon-client/src/gfx/hd/smoke.rs @@ -46,6 +46,8 @@ const MAX_INDICES: usize = 120_000; pub const MAX_LIGHTS: usize = 16; /// How fast the wind carries smoke (blocks per second, x and z). const WIND: [f32; 2] = [1.6, 1.2]; +/// The thinnest a trail is drawn, in blocks of radius (a cell is `CELL`). +const MIN_TUBE: f32 = 3.6; /// Smoke is on unless `HORIZON_HD_SMOKE=0`. pub fn smoke_enabled() -> bool { @@ -402,6 +404,16 @@ fn bake(s: &HdSmoke) -> Option { // Spreading thins it (the core's mass over a wider tube), and it fades out towards its end. let thin = (r0 / radius).powf(0.5); let density = s.shape[2] * (1.0 - u).powi(2) * thin * (t / 0.25).min(1.0).max(0.2); + // A tube thinner than the grid's cells is sampled unevenly (cells near its axis get it, their + // neighbours miss it): a chain of blobs. Trails are kept at least a cell and a bit wide, with + // the same mass per length, so a young trail is a continuous ribbon. + let d = [s.b[0] - s.a[0], s.b[1] - s.a[1], s.b[2] - s.a[2]]; + let tube = d[0] * d[0] + d[1] * d[1] + d[2] * d[2] > 0.25; + let (radius, density) = if tube && radius < MIN_TUBE { + (MIN_TUBE, density * radius / MIN_TUBE) + } else { + (radius, density) + }; let heat = s.shape[3] * (-t / 1.5).exp(); let clear_amount = (1.0 - u).powf(0.8); let clear = s.motion[1] * (1.0 + 0.4 * u); diff --git a/crates/horizon-client/src/gfx/hd/smoke_grid.wgsl b/crates/horizon-client/src/gfx/hd/smoke_grid.wgsl index 01b6e082a..0adcd55f6 100644 --- a/crates/horizon-client/src/gfx/hd/smoke_grid.wgsl +++ b/crates/horizon-client/src/gfx/hd/smoke_grid.wgsl @@ -40,7 +40,7 @@ fn fs_smoke_grid(in: FullOut) -> @location(0) vec4 { let seed = segs[i + 3u].x; let len = sqrt(len2); // Bulges along the tube, so it is not a pipe. - let r = pa.w * (1.0 + 0.22 * sin(along * len * 0.6 + seed * 40.0)); + let r = pa.w * (1.0 + 0.07 * sin(along * len * 0.35 + seed * 40.0)); if d < r && pb.w > 0.0 { let q = d / r; var w = (1.0 - q * q);