Skip to content

Commit 4ba2492

Browse files
demo: carry the raster's walk forward across a Vertical Hold change too
The browser demo is a port of the plugin's own GLSL, so it had the same defect the plugin just lost: the roll was `VerticalHold * Time` in the shader, which moves by `Time * delta` the instant the control changes — and in a page `Time` is how long the tab has been open. Because the roll is wrapped by `fract`, dragging the slider did not start a roll, it dropped the picture at an arbitrary vertical offset. The walk is now accumulated on the page side and handed to the shader as `VerticalRoll`, exactly as OldCathode.cpp hands it to the plugin's copy. The `VerticalHold` uniform still goes over as well, because the rolling bar's width is an amplitude and wants the raw value. **The demo is where this matters most.** A visitor who opens the page is guaranteed to drag these sliders — that is what the page is for — so the one place the bug was certain to be seen was the one place it was still in. Checked in a browser: the shader compiles, the picture renders, and taking Vertical Hold from 0 to 0.35 a minute into the page leaves the picture where it was and starts it crawling, rather than jumping it somewhere unrelated.
1 parent cb37170 commit 4ba2492

1 file changed

Lines changed: 37 additions & 1 deletion

File tree

demo/plugin.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,32 @@ const MASKS = [
6363
{ name: 'RGB Stripe', spill: 0.15, gain: 2.308 },
6464
];
6565

66+
// How far the raster has walked, carried forward across a Vertical Hold change.
67+
//
68+
// The roll used to be VerticalHold * Time in the shader. That moves it by
69+
// Time * delta the instant the control changes, and here Time is how long the
70+
// page has been open -- and because fract wraps the result, the picture does not
71+
// speed up, it lands somewhere arbitrary. Dragging the slider read as the raster
72+
// teleporting rather than the hold slipping. Mirrors OldCathode.h.
73+
let rollAnchor = 0;
74+
let rollAnchorTime = 0;
75+
let rollAnchorHold = -1;
76+
77+
function verticalRoll(hold, seconds) {
78+
if (rollAnchorHold < 0) {
79+
// First frame: anchor stays at zero, so this is exactly the old product
80+
// until the control is touched.
81+
rollAnchorHold = hold;
82+
} else if (hold !== rollAnchorHold) {
83+
// Once per change, not once per frame.
84+
rollAnchor += (seconds - rollAnchorTime) * rollAnchorHold * 0.65;
85+
rollAnchorTime = seconds;
86+
rollAnchorHold = hold;
87+
}
88+
89+
return rollAnchor + (seconds - rollAnchorTime) * hold * 0.65;
90+
}
91+
6692
const signalWidth = (sys) => Math.round(4 * sys.subcarrierMHz * sys.activeLineMicroseconds);
6793
const signalHeight = (sys) => sys.activeLines;
6894

@@ -170,6 +196,13 @@ uniform float Hum;
170196
171197
//Timebase
172198
uniform float VerticalHold;
199+
200+
//How far the raster has walked, in fractions of a field. NOT VerticalHold * Time
201+
//-- an absolute product jumps the picture to an unrelated offset the instant the
202+
//control moves, because the roll wraps. The page side anchors it and hands over
203+
//the position reached. Mirrors OldCathode.h. (No backticks in here: this shader
204+
//lives in a JS template literal, and one would end it.)
205+
uniform float VerticalRoll;
173206
uniform float Jitter;
174207
uniform float Tracking;
175208
uniform float HeadSwitch;
@@ -365,7 +398,7 @@ void main()
365398
366399
//Vertical hold: the field no longer starts where the flyback expects it to,
367400
//so the whole raster walks and takes the blanking interval with it.
368-
float srcY = fract( uv.y + VerticalHold * Time * 0.65 );
401+
float srcY = fract( uv.y + VerticalRoll );
369402
370403
float lineIdx = floor( srcY * SignalSize.y );
371404
float lineRnd = rnd( lineIdx, FrameIndex, 5.0 ) - 0.5;
@@ -883,6 +916,9 @@ function createRenderer(gl, quad) {
883916
signalShader.set('Hum', params.get('hum'));
884917

885918
signalShader.set('VerticalHold', params.get('verticalHold'));
919+
// The anchored walk. The control itself still goes over as well, because
920+
// the rolling bar's width is an amplitude and wants the raw value.
921+
signalShader.set('VerticalRoll', verticalRoll(params.get('verticalHold'), time));
886922
signalShader.set('Jitter', params.get('jitter'));
887923
signalShader.set('Tracking', params.get('tracking'));
888924
signalShader.set('HeadSwitch', params.get('headSwitch'));

0 commit comments

Comments
 (0)