Skip to content

Intermittent 1px column at outer canvas edges on scene tiles #9

Description

@dfattal

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

  1. 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.
  2. 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.
  3. 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

  1. Open samples/hello-cube/ or samples/splat/ in the DisplayXR Browser on SR hardware.
  2. Look at the extreme left and right edges of the canvas against the page background.
  3. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions