Symptom
On scene (three.js) tiles, a one-pixel column is visible at each outer edge of the canvas — one eye's column at the far left of the element box, the other eye's at the far right. Instead of dissolving into the page, they read as a hard line, so the tile does not blend the way EdgeFeather intends.
Reported from a live look on Leia SR hardware (David, 2026-08-14). Affects three.js/scene tiles generally, not one sample.
Why this is the feather's problem specifically
Image and video tiles bake their own feather into the SBS buffer inside the SDK (addImage/addVideo own those buffers). Scene tiles cannot — the app owns the canvas — so the fade is a per-eye render pass, EdgeFeather in js/inline3d-three.js. If the pass misses the outermost column, that column arrives at the weave at full alpha and survives to the display as a hard edge.
Candidate causes, roughly in order
- The ramp never reaches zero at the boundary.
EdgeFeather multiplies the framebuffer by smoothstep(0.0, fx, vUv.x) * smoothstep(0.0, fx, 1.0 - vUv.x). The first texel's centre sits at vUv.x = 0.5 / vp.width, not 0 — so its alpha is small but non-zero. Small residual alpha on a bright scene against a dark page is exactly a faint hairline. Worth testing a ramp that is clamped hard to 0 over the outermost texel, or biasing the smoothstep edge so the first texel lands at or below 0.
- Viewport rounding leaves a column neither eye writes.
layer.getViewport() reports backing-store px; if the two eye viewports do not exactly tile canvas.width (odd widths, or a renderScale that rounds), a column is written by the scene pass but never covered by the feather quad — or the reverse.
- Weave-side un-squeeze sampling. Each eye's half is stretched 2× horizontally. Clamped edge sampling can replicate the outermost source column into the destination without the fade ever applying. If so this is browser-side, not SDK-side, and the fix belongs in the weave rather than in
EdgeFeather.
(1) and (2) are testable purely in-page. (3) needs the weave.
Repro
- Open
samples/hello-cube/ or samples/splat/ in the DisplayXR Browser on SR hardware.
- Look at the extreme left and right edges of the canvas against the page background.
- Compare against an image tile (
samples/windows/), which bakes its feather in the SDK — if image tiles are clean and scene tiles are not, that isolates it to EdgeFeather and rules out (3).
That comparison is the first thing to run; it splits the candidate list in half.
Notes
Symptom
On scene (three.js) tiles, a one-pixel column is visible at each outer edge of the canvas — one eye's column at the far left of the element box, the other eye's at the far right. Instead of dissolving into the page, they read as a hard line, so the tile does not blend the way
EdgeFeatherintends.Reported from a live look on Leia SR hardware (David, 2026-08-14). Affects three.js/scene tiles generally, not one sample.
Why this is the feather's problem specifically
Image and video tiles bake their own feather into the SBS buffer inside the SDK (
addImage/addVideoown those buffers). Scene tiles cannot — the app owns the canvas — so the fade is a per-eye render pass,EdgeFeatherinjs/inline3d-three.js. If the pass misses the outermost column, that column arrives at the weave at full alpha and survives to the display as a hard edge.Candidate causes, roughly in order
EdgeFeathermultiplies the framebuffer bysmoothstep(0.0, fx, vUv.x) * smoothstep(0.0, fx, 1.0 - vUv.x). The first texel's centre sits atvUv.x = 0.5 / vp.width, not0— so its alpha is small but non-zero. Small residual alpha on a bright scene against a dark page is exactly a faint hairline. Worth testing a ramp that is clamped hard to 0 over the outermost texel, or biasing the smoothstep edge so the first texel lands at or below 0.layer.getViewport()reports backing-store px; if the two eye viewports do not exactly tilecanvas.width(odd widths, or arenderScalethat rounds), a column is written by the scene pass but never covered by the feather quad — or the reverse.EdgeFeather.(1) and (2) are testable purely in-page. (3) needs the weave.
Repro
samples/hello-cube/orsamples/splat/in the DisplayXR Browser on SR hardware.samples/windows/), which bakes its feather in the SDK — if image tiles are clean and scene tiles are not, that isolates it toEdgeFeatherand rules out (3).That comparison is the first thing to run; it splits the candidate list in half.
Notes
EdgeFeatherpredates them, andsamples/splatmerely uses it. Expecthello-cubeto show the same thing.