You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vertical Hold: stop a hold change teleporting the raster
The second half of stoatworks-labs/orrery#6, which came in from an external
user, applied here. Orrery fixed it in 6457f74; the same arithmetic is in this
plugin and in every other one in the fleet that drives a rate off an absolute
clock.
The signal shader rolled the raster with `VerticalHold * Time * 0.65`, so a
change to the control moves the roll by `Time * delta` -- and `Time` is however
long the composition has been open, which an hour in is a jump of hundreds of
fields. Because the roll is wrapped by `fract`, the picture does not slide to
the new rate: it lands at an unrelated vertical offset. It reads as the raster
teleporting rather than as the hold slipping, which is a worse bug than the one
the control is imitating.
So the walk is now accumulated on the host side and handed to the shader as
`VerticalRoll`, a position rather than a product. On a change to the control the
roll reached so far is carried forward and the walk continues from there at the
new rate. Once per change rather than per frame, so nothing accumulates and the
frame rate still cannot move the raster. The anchor starts at time zero at roll
zero, which leaves the value identical to the old product until the control is
first touched -- that is what keeps tools/sweep.py and every rendered-frame
comparison measuring what they measured before.
`VerticalHold` still goes over as well, because the rolling bar's width is an
amplitude and wants the raw value; only the phase use moved.
The OpenFX build mirrors the shader on the CPU, so it gains the same
`verticalRoll` field -- but sets it to the plain `verticalHold * time * 0.65`
product, deliberately. That host renders arbitrary times in arbitrary order and
can keyframe Vertical Hold, so a running carry there would make a frame depend
on which frames happened to be rendered before it. Both sides say so at the
point where the difference would otherwise look like drift between the mirrors.
octest grows --roll, which reads the roll either side of a change rather than
comparing rendered frames: `fract` wraps it, so a jump of a whole number of
fields renders identically and two frames would match for entirely the wrong
reason. It runs ahead of the GL context, so a machine without a GPU can still
run it. Checked against the old arithmetic first: it fails there, and by 2224
fields on the step out of zero.
sweep.py still finds all 34 parameters live, Vertical Hold among them, and
--presets still passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0 commit comments