From a7da90fdfcbc17673cccb9f761930ccb812fcfe9 Mon Sep 17 00:00:00 2001 From: quanticsoul4772 <71096528+quanticsoul4772@users.noreply.github.com> Date: Sun, 25 Oct 2026 16:51:56 -0700 Subject: [PATCH] fix(effects): run no sharpen pass when its slider is at 0 (#1398) Disable the sharpen pass when its intensity is zero. Contribution by @quanticsoul4772. --- changelog.d/1398-sharpen-zero-off.md | 2 ++ docs/CURRENT-STATE.md | 2 ++ src/ui/visualEffects.js | 14 +++++++++++++- src/ui/visualEffects.test.mjs | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 changelog.d/1398-sharpen-zero-off.md diff --git a/changelog.d/1398-sharpen-zero-off.md b/changelog.d/1398-sharpen-zero-off.md new file mode 100644 index 000000000..ab05aa6f2 --- /dev/null +++ b/changelog.d/1398-sharpen-zero-off.md @@ -0,0 +1,2 @@ +- The Sharpen slider at 0 now turns the sharpen pass off instead of still + sharpening at a low amount (quanticsoul4772, #1398). diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 07daef46c..e2e24fc7d 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -1301,6 +1301,8 @@ Stopping the controller revokes animation before asynchronous UI teardown; final destruction removes its stages and restores the borrowed bloom configuration. Snow's sideways sway stays within a fixed range at any session age; Wind scales its amplitude. +Sharpen runs only when enabled with intensity above 0.001. At slider zero its +stage is disabled; raising the slider resumes it when sharpen is enabled. ## Display control ownership diff --git a/src/ui/visualEffects.js b/src/ui/visualEffects.js index 8b5234ef2..9d10f0cef 100644 --- a/src/ui/visualEffects.js +++ b/src/ui/visualEffects.js @@ -159,18 +159,30 @@ export class VisualEffects { this.requestRender('bloom'); } + /** + * Sharpen runs only when it is on and its slider is above 0, as the style + * stages do: the pass costs the same at any amount (~1.5 ms GPU per frame + * on the Arc, 2026-10-24), and `0.1 + value * 2` still sharpened at 0. + */ + syncSharpenEnabled() { + if (this.stopped || !this.sharpenStage) return; + this.sharpenStage.enabled = + this.sharpenEnabled && this.sharpenIntensity > 0.001; + } + applySharpenIntensity(value) { if (this.stopped) return; this.sharpenIntensity = value; if (this.sharpenStage) this.sharpenStage.uniforms.amount = 0.1 + value * 2.0; + this.syncSharpenEnabled(); this.requestRender('sharpen'); } setSharpenEnabled(enabled) { if (this.stopped) return; this.sharpenEnabled = !!enabled; - if (this.sharpenStage) this.sharpenStage.enabled = this.sharpenEnabled; + this.syncSharpenEnabled(); this.requestRender('sharpen'); } diff --git a/src/ui/visualEffects.test.mjs b/src/ui/visualEffects.test.mjs index 68fa45962..9e9542c52 100644 --- a/src/ui/visualEffects.test.mjs +++ b/src/ui/visualEffects.test.mjs @@ -224,6 +224,24 @@ test('sharpen uses the existing uniform scale and keeps values while disabled', f.effects.destroy(); }); +test('sharpen at 0 runs no pass, and comes back with the slider', () => { + const f = fixture(); + f.effects.initPostProcess(0.49); + f.effects.setSharpenEnabled(true); + assert.equal(f.effects.sharpenStage.enabled, true); + f.effects.applySharpenIntensity(0); + assert.equal( + f.effects.sharpenStage.enabled, + false, + 'no residual sharpen at 0', + ); + f.effects.setSharpenEnabled(true); + assert.equal(f.effects.sharpenStage.enabled, false, 'on at 0 is still off'); + f.effects.applySharpenIntensity(0.2); + assert.equal(f.effects.sharpenStage.enabled, true); + f.effects.destroy(); +}); + test('stop revokes pending work immediately but retains stages until final destruction', () => { const f = fixture(); f.effects.initStyles();