Skip to content

Commit faaeea3

Browse files
committed
Revert "Add a round-pixels slider"
This reverts commit 0005569.
1 parent 0005569 commit faaeea3

3 files changed

Lines changed: 5 additions & 102 deletions

File tree

index.html

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,6 @@
225225
<input id="glow" type="range" min="0" max="2" step="0.01" value="2" />
226226
<span class="val" id="glow-val">2.00</span>
227227
</div>
228-
<div class="row">
229-
<label for="roundness">Round pixels</label>
230-
<input id="roundness" type="range" min="0" max="1" step="0.01" value="0" />
231-
<span class="val" id="roundness-val">0.00</span>
232-
</div>
233228
<div class="row">
234229
<label for="volume">Volume</label>
235230
<input id="volume" type="range" min="0" max="1" step="0.01" value="0.5" />

src/main.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const PICTURE_KEY = 'abusejs.picture'
5555
* The same four numbers appear as the `value` attributes in index.html and as
5656
* CrtFilter's own fallbacks. Keep the three in step.
5757
*/
58-
const PICTURE_DEFAULTS = { brightness: 1.05, contrast: 1.21, glow: 2, roundness: 0, volume: 0.5 }
58+
const PICTURE_DEFAULTS = { brightness: 1.05, contrast: 1.21, glow: 2, volume: 0.5 }
5959

6060
function loadPictureSettings(): typeof PICTURE_DEFAULTS {
6161
try {
@@ -68,10 +68,6 @@ function loadPictureSettings(): typeof PICTURE_DEFAULTS {
6868
contrast: Number(parsed.contrast) || PICTURE_DEFAULTS.contrast,
6969
// Same reasoning as volume: 0 glow is a deliberate setting, not a miss.
7070
glow: Number.isFinite(Number(parsed.glow)) ? Number(parsed.glow) : PICTURE_DEFAULTS.glow,
71-
// 0 is the default and a deliberate setting both, so `||` will not do.
72-
roundness: Number.isFinite(Number(parsed.roundness))
73-
? Number(parsed.roundness)
74-
: PICTURE_DEFAULTS.roundness,
7571
// `||` would turn a deliberate 0 back into the default, but 0 is the
7672
// default here anyway - be explicit so it stays correct if that changes.
7773
volume: Number.isFinite(volume) ? volume : PICTURE_DEFAULTS.volume,
@@ -86,36 +82,31 @@ function mountPictureControls(
8682
crt: CrtFilter,
8783
audio: AudioBank,
8884
initialGlow: number,
89-
initialRoundness: number,
9085
initialVolume: number,
9186
onVolumeChange: (muted: boolean) => void,
9287
): void {
9388
const panel = document.getElementById('controls') as HTMLDivElement | null
9489
const brightness = document.getElementById('brightness') as HTMLInputElement | null
9590
const contrast = document.getElementById('contrast') as HTMLInputElement | null
9691
const glow = document.getElementById('glow') as HTMLInputElement | null
97-
const roundness = document.getElementById('roundness') as HTMLInputElement | null
9892
const volume = document.getElementById('volume') as HTMLInputElement | null
9993
const brightnessVal = document.getElementById('brightness-val')
10094
const contrastVal = document.getElementById('contrast-val')
10195
const glowVal = document.getElementById('glow-val')
102-
const roundnessVal = document.getElementById('roundness-val')
10396
const volumeVal = document.getElementById('volume-val')
10497
const reset = document.getElementById('reset-levels')
105-
if (!panel || !brightness || !contrast || !glow || !roundness || !volume) return
106-
if (!brightnessVal || !contrastVal || !glowVal || !roundnessVal || !volumeVal || !reset) return
98+
if (!panel || !brightness || !contrast || !glow || !volume) return
99+
if (!brightnessVal || !contrastVal || !glowVal || !volumeVal || !reset) return
107100

108101
const sync = (persist: boolean) => {
109102
crt.brightness = Number(brightness.value)
110103
crt.contrast = Number(contrast.value)
111104
crt.glow = Number(glow.value)
112-
crt.roundness = Number(roundness.value)
113105
audio.volume = Number(volume.value)
114106

115107
brightnessVal.textContent = crt.brightness.toFixed(2)
116108
contrastVal.textContent = crt.contrast.toFixed(2)
117109
glowVal.textContent = crt.glow.toFixed(2)
118-
roundnessVal.textContent = crt.roundness.toFixed(2)
119110
volumeVal.textContent = audio.muted ? 'off' : audio.volume.toFixed(2)
120111

121112
if (persist) {
@@ -126,7 +117,6 @@ function mountPictureControls(
126117
brightness: crt.brightness,
127118
contrast: crt.contrast,
128119
glow: crt.glow,
129-
roundness: crt.roundness,
130120
volume: audio.volume,
131121
}),
132122
)
@@ -139,12 +129,11 @@ function mountPictureControls(
139129
brightness.value = String(crt.brightness)
140130
contrast.value = String(crt.contrast)
141131
glow.value = String(initialGlow)
142-
roundness.value = String(initialRoundness)
143132
volume.value = String(initialVolume)
144133
sync(false)
145134

146135
let wasMuted = audio.muted
147-
for (const slider of [brightness, contrast, glow, roundness, volume]) {
136+
for (const slider of [brightness, contrast, glow, volume]) {
148137
slider.addEventListener('input', () => {
149138
sync(true)
150139
if (audio.muted !== wasMuted) {
@@ -162,7 +151,6 @@ function mountPictureControls(
162151
brightness.value = String(PICTURE_DEFAULTS.brightness)
163152
contrast.value = String(PICTURE_DEFAULTS.contrast)
164153
glow.value = String(PICTURE_DEFAULTS.glow)
165-
roundness.value = String(PICTURE_DEFAULTS.roundness)
166154
volume.value = String(PICTURE_DEFAULTS.volume)
167155
sync(true)
168156
reset.blur()
@@ -318,7 +306,7 @@ async function start() {
318306
crt.intensity = on ? 1 : 0
319307
}
320308

321-
mountPictureControls(crt, audio, picture.glow, picture.roundness, picture.volume, (muted) => {
309+
mountPictureControls(crt, audio, picture.glow, picture.volume, (muted) => {
322310
// Unmuting has to (re)start the soundtrack, since it never started while
323311
// silent - and the AudioContext may only just have been unlocked.
324312
if (muted) music.stop()
@@ -346,8 +334,6 @@ async function start() {
346334
app.stage.filterArea = app.screen
347335
crt.pixelScale = crtPixelScale(height)
348336
crt.gridPeriod = crtGridPeriod(zoom, app.renderer.resolution)
349-
// One game pixel, for the roundness mask - see CrtFilter.pixelSize.
350-
crt.pixelSize = zoom * app.renderer.resolution
351337
crt.setScreenSize(width, height)
352338
}
353339
applySize()

src/render/CrtFilter.ts

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ uniform float uIntensity;
4040
uniform vec2 uScreenSize;
4141
uniform float uBrightness;
4242
uniform float uContrast;
43-
uniform float uRoundness;
44-
uniform float uPixelSize;
4543
4644
// --- constants, in the original's 960x540 present space ---
4745
const float CURVE = 9.0; // px the image is squeezed at the edges
@@ -62,23 +60,6 @@ const float VIGNETTE_INNER = 0.45;
6260
const float VIGNETTE_OUTER = 0.95;
6361
const float VIGNETTE_ALPHA = 0.5;
6462
65-
// Superellipse exponents the roundness slider sweeps between. 8 still reads as
66-
// a square - only the very corners are off - and 2 is a true circle.
67-
const float SQUIRCLE_SQUARE = 8.0;
68-
const float SQUIRCLE_ROUND = 2.0;
69-
// How dark the gap between dots goes at full roundness. Below 1 so the picture
70-
// keeps some floor rather than dropping to black between pixels.
71-
const float DOT_DEPTH = 0.85;
72-
// Average of the dot mask over one cell, which is what the brightness
73-
// compensation has to undo. Straight lines in the feather width, fitted to the
74-
// mask integrated numerically at each end - 1 - pi/4 is the right answer only
75-
// for a hard-edged circle, and the feather widens it by more than it looks:
76-
// at the widest setting a square already averages 0.29, not 0.02.
77-
const float GAP_SQUARE_BASE = 0.026;
78-
const float GAP_SQUARE_SLOPE = 0.876;
79-
const float GAP_ROUND_BASE = 0.218;
80-
const float GAP_ROUND_SLOPE = 0.703;
81-
8263
vec3 sampleScene(vec2 frameUv) {
8364
// Outside the tube there is nothing behind the glass.
8465
if (frameUv.x < 0.0 || frameUv.x > 1.0 || frameUv.y < 0.0 || frameUv.y > 1.0) return vec3(0.0);
@@ -144,36 +125,6 @@ void main() {
144125
float grilleAlpha = col < 2.0 ? GRILLE_ALPHA : GRILLE_ALPHA_B;
145126
color = mix(color, tint, grilleAlpha);
146127
147-
// --- pixel roundness --------------------------------------------------
148-
// Shapes each *game* pixel, so it needs uPixelSize rather than the grille's
149-
// uGridPeriod - those are the same thing only at zoom 3 and above.
150-
//
151-
// A superellipse, |x|^n + |y|^n = 1: n large is a square with the corners
152-
// barely off, n = 2 is a circle. Sweeping the exponent rather than mixing
153-
// in a circle keeps every intermediate value a real shape instead of a
154-
// cross-fade between two, so the slider reads as one dial being turned.
155-
//
156-
// Carving gaps costs light, so the level is put back below - see there.
157-
if (uRoundness > 0.0 && uPixelSize >= 2.0) {
158-
vec2 cell = fract(frag / uPixelSize) * 2.0 - 1.0;
159-
float n = mix(SQUIRCLE_SQUARE, SQUIRCLE_ROUND, uRoundness);
160-
float d = pow(pow(abs(cell.x), n) + pow(abs(cell.y), n), 1.0 / n);
161-
// Feather over roughly a device pixel so a dot has an edge rather than
162-
// a staircase, but kept narrow: a wide ramp shades most of the cell
163-
// instead of just its corners, and the picture goes out with it.
164-
float feather = clamp(1.2 / uPixelSize, 0.05, 0.3);
165-
float mask = smoothstep(1.0 - feather, 1.0, d);
166-
167-
// Carving gaps removes light, and a control labelled "round" that also
168-
// dims is two controls. Divide the mask by its own average so the cell
169-
// keeps the level it came in with, and only its shape changes.
170-
float gap = mix(
171-
GAP_SQUARE_BASE + GAP_SQUARE_SLOPE * feather,
172-
GAP_ROUND_BASE + GAP_ROUND_SLOPE * feather,
173-
uRoundness);
174-
color *= (1.0 - uRoundness * DOT_DEPTH * mask) / (1.0 - uRoundness * DOT_DEPTH * gap);
175-
}
176-
177128
// --- slow rolling band ------------------------------------------------
178129
float bandSpan = size.y + 160.0 * px;
179130
float bandY = mod(uTime * BAND_SPEED * px, bandSpan) - 160.0 * px;
@@ -223,10 +174,6 @@ export interface CrtOptions {
223174
brightness?: number
224175
/** 1 = unchanged, pivoting around mid grey. Applied after the CRT pass. */
225176
contrast?: number
226-
/** 0 square, 1 round. See the shader's pixel-roundness block. */
227-
roundness?: number
228-
/** One game pixel in device pixels - `zoom * resolution`. */
229-
pixelSize?: number
230177
}
231178

232179
export class CrtFilter extends Filter {
@@ -240,8 +187,6 @@ export class CrtFilter extends Filter {
240187
uScreenSize: { value: new Float32Array([960, 540]), type: 'vec2<f32>' },
241188
uBrightness: { value: options.brightness ?? 1.05, type: 'f32' },
242189
uContrast: { value: options.contrast ?? 1.21, type: 'f32' },
243-
uRoundness: { value: options.roundness ?? 0, type: 'f32' },
244-
uPixelSize: { value: options.pixelSize ?? 3, type: 'f32' },
245190
})
246191

247192
super({
@@ -264,8 +209,6 @@ export class CrtFilter extends Filter {
264209
uGridPeriod: number
265210
uGlow: number
266211
uIntensity: number
267-
uRoundness: number
268-
uPixelSize: number
269212
uScreenSize: Float32Array
270213
uBrightness: number
271214
uContrast: number
@@ -286,27 +229,6 @@ export class CrtFilter extends Filter {
286229
this.uniforms.uGridPeriod = value
287230
}
288231

289-
/**
290-
* One game pixel in device pixels - `zoom * resolution`.
291-
*
292-
* Not `gridPeriod`: that is a scanline cycle, which is grown to at least
293-
* three device pixels so the mask can draw at all. Rounding wants the real
294-
* pixel, and switches itself off below two device pixels because there is
295-
* nothing there to shape.
296-
*/
297-
set pixelSize(value: number) {
298-
this.uniforms.uPixelSize = value
299-
}
300-
301-
/** 0 leaves pixels square; 1 makes them round. */
302-
get roundness(): number {
303-
return this.uniforms.uRoundness
304-
}
305-
306-
set roundness(value: number) {
307-
this.uniforms.uRoundness = Math.max(0, Math.min(1, value))
308-
}
309-
310232
/**
311233
* How much bloom and convergence ghosting to add. 1 is the amount the
312234
* original effect was authored with; 0 leaves the picture sharp.

0 commit comments

Comments
 (0)