mirror of
https://github.com/samvallad33/vestige.git
synced 2026-07-02 22:01:01 +02:00
fix(cinema): tighten storm framing so the bloom halo never clips
The rainbow storm looked next-dimensional but still clipped the edges — the additive bloom halo extends each particle's glow well past its geometric radius, so the visible cloud was bigger than the contain sphere. - spawn radius 15 -> 8 (particles start inside the shell, no asymmetric inward yank) - sandbox fitRadius margin 0.55 -> 0.40 (leaves room for the bloom halo) - camera band tightened + pushed farther (30-44) so the contained cloud sits small + centered; director standoff clamped into that band in centerOnOrigin mode so the camera never fights the per-frame clamp (the off-center jump). 937 tests + build green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
65c801bc2f
commit
782399adb1
3 changed files with 19 additions and 6 deletions
|
|
@ -168,6 +168,11 @@ export class CinemaDirector {
|
|||
else if (shot.move === 'pull_back') standoff *= 1.5;
|
||||
else if (shot.move === 'crane') standoff *= 1.8;
|
||||
}
|
||||
// In centered (WebGPU storm) mode the subject is pinned to the origin and
|
||||
// the sandbox clamps the camera to a far band. Keep the directed standoff
|
||||
// INSIDE that band so the camera never fights the clamp (which read as an
|
||||
// off-center jump) — variety here comes from angle + orbit, not distance.
|
||||
if (this.opts.centerOnOrigin) standoff = Math.max(31, Math.min(43, standoff));
|
||||
return out.copy(nodePos).addScaledVector(_tmpDir, standoff);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@ import type { SemanticRole, SemanticComputeStorm } from './storm';
|
|||
// The storm lives at the world origin, permanently. The camera always looks here
|
||||
// and is clamped to a safe distance band so the subject can never leave frame.
|
||||
const ORIGIN = new THREE.Vector3(0, 0, 0);
|
||||
const MIN_CAM_DIST = 18;
|
||||
const MAX_CAM_DIST = 46;
|
||||
// Keep the camera in a narrow, fairly FAR band so the contained storm always
|
||||
// sits comfortably small and centered in frame (a closer camera makes the cloud
|
||||
// fill — and spill past — the edges once the bloom halo is added).
|
||||
const MIN_CAM_DIST = 30;
|
||||
const MAX_CAM_DIST = 44;
|
||||
|
||||
export function isWebGPUSupported(): boolean {
|
||||
return typeof navigator !== 'undefined' && 'gpu' in navigator;
|
||||
|
|
@ -185,11 +188,14 @@ export class CinemaSandbox {
|
|||
}
|
||||
this.camera.lookAt(ORIGIN);
|
||||
|
||||
// Size the containment sphere to the camera's FOV at the origin so the
|
||||
// storm always fully fits the frame with margin.
|
||||
// Size the containment sphere to the camera's VERTICAL FOV at the origin
|
||||
// (the limiting dimension on a landscape frame). The 0.40 factor leaves
|
||||
// generous room for the additive BLOOM HALO — each particle's glow spreads
|
||||
// well beyond its geometric position, so the visible cloud is much larger
|
||||
// than the radius; an aggressive margin is what actually stops the clip.
|
||||
const dist = this.camera.position.length();
|
||||
const vfov = (this.camera.fov * Math.PI) / 180;
|
||||
const fitRadius = Math.tan(vfov / 2) * dist * 0.55;
|
||||
const fitRadius = Math.tan(vfov / 2) * dist * 0.4;
|
||||
this.storm.setContainRadius(fitRadius);
|
||||
|
||||
await this.storm.update(deltaSeconds);
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ export class SemanticComputeStorm {
|
|||
this.renderer = renderer;
|
||||
this.scene = scene;
|
||||
this.count = opts.count ?? 150_000;
|
||||
const spawn = opts.spawnRadius ?? 15;
|
||||
// Spawn inside the contained zone so particles don't start outside the
|
||||
// shell and get yanked inward asymmetrically (which read as off-center).
|
||||
const spawn = opts.spawnRadius ?? 8;
|
||||
|
||||
const positions = new Float32Array(this.count * 3);
|
||||
const velocities = new Float32Array(this.count * 3);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue