implemented real bpm analize
This commit is contained in:
+14
-11
@@ -246,7 +246,7 @@ impl Arch {
|
||||
match self {
|
||||
// Wide, slow, thin, dim. Knot (ordered) backbone, shell barely on.
|
||||
Arch::Ambient => Regime {
|
||||
scale: 0.95,
|
||||
scale: 1.00,
|
||||
melt: 0.3,
|
||||
glow: 0.40,
|
||||
speed: 0.55,
|
||||
@@ -262,7 +262,7 @@ impl Arch {
|
||||
// Contracting toward a dense core; everything ramps with tension
|
||||
// (see Breakcore::update — these are the *base* before tension).
|
||||
Arch::Build => Regime {
|
||||
scale: 0.78,
|
||||
scale: 0.84,
|
||||
melt: 0.7,
|
||||
glow: 0.60,
|
||||
speed: 0.9,
|
||||
@@ -292,7 +292,7 @@ impl Arch {
|
||||
},
|
||||
// Hollowed out after a drop: medium, soft, cool, slow.
|
||||
Arch::Breakdown => Regime {
|
||||
scale: 0.85,
|
||||
scale: 0.90,
|
||||
melt: 0.45,
|
||||
glow: 0.50,
|
||||
speed: 0.7,
|
||||
@@ -307,7 +307,7 @@ impl Arch {
|
||||
},
|
||||
// Balanced sustained default.
|
||||
Arch::Groove => Regime {
|
||||
scale: 0.82,
|
||||
scale: 0.88,
|
||||
melt: 0.5,
|
||||
glow: 0.65,
|
||||
speed: 1.0,
|
||||
@@ -636,7 +636,7 @@ impl Breakcore {
|
||||
self.sp_scale.step(scale_t, 14.0, dt);
|
||||
self.sp_tube
|
||||
.step(rg.tube + 0.05 * b.mid + 0.02 * b.mid_on, 11.0, dt);
|
||||
self.sp_dist.step(3.4 - 0.9 * b.low, 6.0, dt);
|
||||
self.sp_dist.step(3.2 - 0.85 * b.low, 6.0, dt);
|
||||
self.sp_glow.step(
|
||||
rg.glow + 0.45 * b.loud + 0.4 * b.flux + 0.35 * tn,
|
||||
9.0,
|
||||
@@ -729,7 +729,10 @@ impl Breakcore {
|
||||
/// shock, so every structure pulses out together on a big hit and the
|
||||
/// bounding sphere (which uses this too) never clips them.
|
||||
fn world_scale(&self) -> f32 {
|
||||
self.sp_scale.x.clamp(0.4, 2.4) * (1.0 + 0.12 * self.shock)
|
||||
// Hard upper bound: this also feeds the bounding-sphere radius, and a
|
||||
// sphere that fills the viewport defeats the background early-out that
|
||||
// protects the GPU. A release/loud spike must not balloon it.
|
||||
self.sp_scale.x.clamp(0.4, 1.8) * (1.0 + 0.12 * self.shock)
|
||||
}
|
||||
|
||||
/// Sample the backbone into the spine slots, blending from→to with the
|
||||
@@ -927,11 +930,11 @@ impl Breakcore {
|
||||
let lo = self.b.loud;
|
||||
let base = oklch(
|
||||
(0.55 + 0.30 * lo + 0.12 * tn).min(0.95),
|
||||
0.10 + 0.06 * lo,
|
||||
0.13 + 0.06 * lo,
|
||||
self.hue_b,
|
||||
);
|
||||
let sat = (0.13 + 0.10 * (lo * 0.5 + self.b.mid * 0.4))
|
||||
* (1.0 - 0.30 * self.b.flatness);
|
||||
let sat = (0.17 + 0.12 * (lo * 0.5 + self.b.mid * 0.4))
|
||||
* (1.0 - 0.25 * self.b.flatness);
|
||||
let acc = oklch((0.62 + 0.28 * lo).min(0.97), sat, self.hue_a);
|
||||
|
||||
let mut u = [0.0f32; UBO_LEN];
|
||||
@@ -946,7 +949,7 @@ impl Breakcore {
|
||||
// row1 scale,tube,glow,ca
|
||||
u[4] = scale;
|
||||
u[5] = self.sp_tube.x;
|
||||
u[6] = self.sp_glow.x.clamp(0.40, 1.2);
|
||||
u[6] = self.sp_glow.x.clamp(0.40, 1.0);
|
||||
// build-up creeps the aberration; release spikes it (drive scales
|
||||
// the swing, not the user's base `ca`).
|
||||
u[7] = ca_px * rg.ca * (1.0 + (0.7 * tn + 2.0 * rel) * dr);
|
||||
@@ -1001,7 +1004,7 @@ impl Breakcore {
|
||||
// row9 swirl_zoom, swirl_rot, bg_glow, beat
|
||||
u[36] = (0.004 + (0.018 * self.b.loud + 0.020 * self.shock) * dr).clamp(0.0, 0.05);
|
||||
u[37] = ((0.006 * self.b.mid + 0.020 * tn) * dr).clamp(0.0, 0.05);
|
||||
u[38] = (0.15 + 0.70 * self.b.loud).clamp(0.0, 1.0);
|
||||
u[38] = (0.05 + 0.40 * self.b.loud).clamp(0.0, 1.0);
|
||||
u[39] = self.b.beat;
|
||||
// points (after 10 std140 rows = 40 f32)
|
||||
for (i, p) in pts.iter().enumerate() {
|
||||
|
||||
+38
-17
@@ -211,7 +211,9 @@ fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
|
||||
// binary hit→white. Bright within ~0.012, gone by ~0.03, so a dense
|
||||
// tangle reads as separated glowing wires, not a filled slab.
|
||||
let dl = max(dmin, 0.0);
|
||||
inten = exp(-dl * dl * 6000.0) + 0.10 * exp(-dl * 30.0);
|
||||
// Tighter halo (0.06·e^-40d, was 0.10·e^-30d) so a dense tangle reads
|
||||
// as separated glowing wires, not one glow mass.
|
||||
inten = exp(-dl * dl * 6000.0) + 0.06 * exp(-dl * 40.0);
|
||||
let tt = select(t, hit_t, hit_t > 0.0);
|
||||
depth = clamp((tt + b) / max(2.0 * sq, 1e-3), 0.0, 1.0);
|
||||
// Reactive volumetric fog: near strands brighter than far.
|
||||
@@ -222,29 +224,44 @@ fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
|
||||
// Shade point (local/rotated space, same as map()).
|
||||
let rp = rot(ro + rd * tt);
|
||||
// Per-structure hue: each layer keeps its own colour identity.
|
||||
let gid = nearest_gid(rp);
|
||||
// `nearest_gid` is a full NP loop, so — like the normal — it is
|
||||
// gated to near-surface pixels; the faint outer glow just uses
|
||||
// the base hue (it is dim enough not to matter) so the expensive
|
||||
// path can never run over a screen-sized halo.
|
||||
var wire = base;
|
||||
if (gid > 2.5) { wire = mix(base, accent, 0.5); } // spokes
|
||||
else if (gid > 1.5) { wire = mix(accent, vec3<f32>(1.0), 0.7); } // debris
|
||||
else if (gid > 0.5) { wire = accent; } // ribs
|
||||
if (dmin < 0.020) {
|
||||
let gid = nearest_gid(rp);
|
||||
if (gid > 2.5) { wire = mix(base, accent, 0.5); } // spokes
|
||||
else if (gid > 1.5) { wire = mix(accent, vec3<f32>(1.0, 0.55, 0.25), 0.6); } // debris (hot)
|
||||
else if (gid > 0.5) { wire = accent; } // ribs
|
||||
}
|
||||
// A little depth blend toward accent keeps the form readable in 3D.
|
||||
let wcol = mix(wire, accent, 0.25 * depth);
|
||||
|
||||
col = wcol * inten;
|
||||
col = col + mix(accent, vec3<f32>(1.0), 0.6) * pow(inten, 6.0) * 0.6;
|
||||
// Hotter exponent + lower weight: only the very centre of a wire
|
||||
// blows toward white, so hue survives across the body.
|
||||
col = col + mix(accent, vec3<f32>(1.0), 0.5) * pow(inten, 8.0) * 0.35;
|
||||
col = col + accent * flash * pow(inten, 3.0) * 0.35; // onset spark
|
||||
|
||||
// Surface lighting — rim/fresnel + a hi-band specular glint give
|
||||
// the tube real 3D form instead of a flat glow ribbon.
|
||||
let n = calc_normal(rp);
|
||||
let vdir = normalize(rot(-rd));
|
||||
let rim_e = mix(4.0, 1.6, flat_n); // noisy → broader rim
|
||||
let rim = pow(1.0 - clamp(dot(n, vdir), 0.0, 1.0), rim_e);
|
||||
col = col + wcol * rim * inten * 0.45;
|
||||
let ldir = normalize(vec3<f32>(0.4, 0.7, -0.55));
|
||||
let hdir = normalize(ldir + vdir);
|
||||
let spec = pow(clamp(dot(n, hdir), 0.0, 1.0), 42.0);
|
||||
col = col + vec3<f32>(1.0) * spec * inten * (0.25 + 0.9 * high_on);
|
||||
// the tube real 3D form. The 6×map() normal is the single most
|
||||
// expensive thing in the shader, so it is gated to pixels that
|
||||
// genuinely landed ON a wire (tiny `dmin`), NOT the whole soft
|
||||
// glow halo. This caps the expensive-pixel count to the thin wire
|
||||
// silhouette regardless of framing — it is what keeps a dense
|
||||
// drop from blowing the GPU frame budget (device-lost).
|
||||
if (dmin < 0.006) {
|
||||
let n = calc_normal(rp);
|
||||
let vdir = normalize(rot(-rd));
|
||||
let rim_e = mix(4.0, 1.6, flat_n); // noisy → broader rim
|
||||
let rim = pow(1.0 - clamp(dot(n, vdir), 0.0, 1.0), rim_e);
|
||||
col = col + wcol * rim * inten * 0.45;
|
||||
let ldir = normalize(vec3<f32>(0.4, 0.7, -0.55));
|
||||
let hdir = normalize(ldir + vdir);
|
||||
let spec = pow(clamp(dot(n, hdir), 0.0, 1.0), 42.0);
|
||||
col = col + vec3<f32>(1.0) * spec * inten * (0.25 + 0.9 * high_on);
|
||||
}
|
||||
|
||||
// Build-up heat: warm toward accent + a warm hot core.
|
||||
col = col + accent * heat * pow(inten, 2.0) * 0.20;
|
||||
@@ -292,8 +309,12 @@ fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
|
||||
// Faint base-hue background so the void breathes with loudness without
|
||||
// ever washing (≤0.05, centre-weighted). Added after feedback so it is a
|
||||
// stable floor, not something the trail can accumulate.
|
||||
// Force a dark *cool* tint (not the raw base hue, which lands olive and
|
||||
// the phosphor feedback then accumulates into a full-frame wash). Tiny
|
||||
// amplitude so it can never build up through the trail.
|
||||
let vig = max(1.0 - 0.75 * length(ndc), 0.0);
|
||||
col = col + base * u.p6.z * vig * 0.05;
|
||||
let bgt = mix(base, vec3<f32>(0.04, 0.08, 0.16), 0.70);
|
||||
col = col + bgt * u.p6.z * vig * 0.02;
|
||||
|
||||
// CRT scanline — depth is audio-driven (loudness + tension) and the
|
||||
// lines crawl with the beat phase, so the "display" feels alive.
|
||||
|
||||
Reference in New Issue
Block a user