shader: gaussian-speck stars + star_aa toggle + bloom/exposure uniforms

star_color's smoothstep(0.5,0.0,d) with scale=80 produced blocky rectangles
at low render_scale. Replace with a gaussian speck: distance to cell center
with exp(-d²/r²) falloff, producing a round 2-3 pixel anti-aliased disk.
star_aa uniform toggles between the gaussian path (desktop default) and the
old square-cell fast path (web default).

Also adds bloom_threshold/bloom_strength/exposure uniform fields to
BlackHoleUniforms (used by later bloom tasks) with safe defaults.
This commit is contained in:
xfy 2026-07-14 23:55:17 +08:00
parent 7d3a8a81ba
commit 0f33d80fd3
4 changed files with 42 additions and 5 deletions

View File

@ -34,6 +34,10 @@ struct BlackHoleUniforms {
planet_count: u32,
steps: u32,
spin: f32,
star_aa: u32,
bloom_threshold: f32,
bloom_strength: f32,
exposure: f32,
_pad5: f32,
};
@ -82,17 +86,29 @@ fn hash13(p: vec3<f32>) -> f32 {
fn star_color(dir: vec3<f32>, intensity: f32) -> vec3<f32> {
let scale = 80.0;
let cell = floor(dir * scale);
let p = dir * scale;
let cell = floor(p);
let h = hash13(cell);
let threshold = 0.985;
if (h > threshold) {
let b = (h - threshold) / (1.0 - threshold);
let col = mix(vec3<f32>(0.6, 0.7, 1.0), vec3<f32>(1.0, 0.9, 0.7), b);
let f = abs(dir * scale - cell);
if (uniforms.star_aa != 0u) {
// Gaussian speck: distance to cell center, soft radial falloff.
// Produces a round 2-3 pixel anti-aliased disk instead of a square.
let center = cell + vec3<f32>(0.5);
let dist = length(p - center);
let radius = 0.25 + b * 0.4;
let falloff = exp(-dist * dist / (radius * radius));
return col * b * falloff * 4.0 * intensity;
} else {
// Original fast path: square-cell smoothstep (blocky but cheap).
let f = abs(p - cell);
let d = max(f.x, max(f.y, f.z));
let falloff = smoothstep(0.5, 0.0, d);
return col * b * falloff * 3.0 * intensity;
}
}
return vec3<f32>(0.0);
}

View File

@ -27,6 +27,11 @@ pub struct BlackHoleParams {
pub planet_count: u32,
// Kerr (Phase 2; unused in Phase 1)
pub spin: f32,
// Quality (Phase 3: cinematic rendering)
pub star_aa: bool,
pub bloom_threshold: f32,
pub bloom_strength: f32,
pub exposure: f32,
}
impl Default for BlackHoleParams {
@ -48,6 +53,10 @@ impl Default for BlackHoleParams {
skybox_intensity: 0.0, // procedural stars only by default
planet_count: 0,
spin: 0.0,
star_aa: if cfg!(target_arch = "wasm32") { false } else { true },
bloom_threshold: 1.0,
bloom_strength: 0.8,
exposure: 1.0,
}
}
}

View File

@ -38,6 +38,10 @@ pub struct BlackHoleUniforms {
pub planet_count: u32,
pub steps: u32,
pub spin: f32, // Phase 2: dimensionless Kerr spin χ = a/M ∈ [0,1].
pub star_aa: u32,
pub bloom_threshold: f32,
pub bloom_strength: f32,
pub exposure: f32,
pub _pad5: f32,
}
@ -70,6 +74,10 @@ impl Default for BlackHoleUniforms {
planet_count: 0,
steps: 300,
spin: 0.0,
star_aa: 1,
bloom_threshold: 1.0,
bloom_strength: 0.8,
exposure: 1.0,
_pad5: 0.0,
}
}

View File

@ -261,5 +261,9 @@ fn mirror_params(
u.planet_count = params.planet_count;
u.steps = params.steps;
u.spin = params.spin;
u.star_aa = params.star_aa as u32;
u.bloom_threshold = params.bloom_threshold;
u.bloom_strength = params.bloom_strength;
u.exposure = params.exposure;
}
}