Skip to content

Interpolate Canvas gradient stops in straight RGBA - #1889

Draft
bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/canvas-gradient-interpolation
Draft

bkaradzic-microsoft wants to merge 1 commit into
BabylonJS:masterfrom
bkaradzic-microsoft:pr/canvas-gradient-interpolation

Conversation

@bkaradzic-microsoft

@bkaradzic-microsoft bkaradzic-microsoft commented Sep 17, 2026

Copy link
Copy Markdown
Member

Landing blocked by stock-stack CI regression. The standalone gradient correction passes its direct Canvas controls, but the unchanged GUI Gradient Linear with transparency validation scene now differs by 33.810% (limit 2.5%) with published Babylon.js 9.21.2. Investigating the interaction with Canvas upload alpha handling. This PR remains draft; references and tolerances will not be weakened to make it pass.

Summary

  • Interpolate Canvas gradient RGB and alpha independently, rather than premultiplying before interpolation and unpremultiplying the result.
  • Apply the same rule to the linear ramp and the radial color interpolator. NanoVG still premultiplies the sampled ramp when compositing.
  • Add exact CPU controls for translucent, fully transparent, opaque, and coincident stops.
  • Add direct Canvas GPU controls for linear and radial translucent gradients over an opaque white backdrop.

Scope (not yet independently landable)

Rebased onto master (36e1c07b). Only gradient interpolation and its tests change. No Babylon.js changes, new Canvas upload arguments, dynamic-mipmap changes, instance-branding changes, dependency updates, fixtures, or tolerances.

The opaque-backdrop GPU controls intentionally avoid depending on any separate JavaScript/Native Canvas upload-alpha repair.

Validation

Windows x64 / D3D11 / Chakra / RelWithDebInfo:

  • Both new CPU/GPU regressions fail with the old interpolation and pass with the fix.
  • All 6 selected native cases pass, including the existing Canvas readback cases.
  • JavaScript suite: 65 passing, 27 optional codec cases pending (plugins disabled).

Stock-stack landing blocker

The unchanged transparent GUI fixture fails on both Windows/D3D11 and Linux/OpenGL CI, while the direct Canvas controls pass. The D3D11 difference is 81,144 / 240,000 pixels (33.810%, with the unchanged 2.5% gate). The stock-gradient baseline passes the same fixture locally.

Published Babylon.js 9.21.2 accepts premulAlpha in updateDynamicTexture, but calls canvas.getCanvasTexture() without forwarding that mode. Native currently exposes the Canvas framebuffer directly. This points to an existing upload-alpha interaction: fixing interpolation alone can remove accidental compensation for a different alpha error. The exact end-to-end repair is not established, so this candidate is not currently independently landable, despite its Native-only source diff.

The PR remains draft. No fixture/reference/tolerance changes, backend exclusion, dependency override, or one-mode Canvas upload workaround will be used to hide this regression.

Latest rebased CI

At head 8b6e8f4b, Linux JavaScriptCore/OpenGL builds and reaches visual validation: 288/289 scenes pass. The sole failure is the same documented GUI Gradient Linear with transparency blocker: 81,359 / 240,000 pixels (33.900%), above the unchanged 2.5% limit. The rebase does not resolve the upload-alpha dependency; this PR remains draft, without changes to references, thresholds, or exclusions.

Copilot AI lite review requested due to automatic review settings September 17, 2026 20:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Updates Canvas gradient interpolation to blend RGB and alpha channels independently in straight RGBA space, while retaining NanoVG premultiplication during compositing.

Changes:

  • Replaces premultiplied/unpremultiplied interpolation in linear and radial gradients with straight RGBA interpolation.
  • Adds CPU regression coverage for translucent, opaque, fully transparent, and coincident stops.
  • Adds GPU readback coverage for linear and radial translucent gradients over an opaque backdrop.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Polyfills/Canvas/Source/Gradient.cpp Implements straight RGBA interpolation for gradient ramps and color sampling.
Apps/UnitTests/Source/Tests.Canvas.Readback.cpp Adds CPU and GPU regression tests for gradient interpolation behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Interpolate RGB and alpha independently in linear and radial gradient
baking. NanoVG performs premultiplication when compositing the ramp.

Cover exact ramp bytes, radial interpolation, transparent and opaque
stops, coincident-stop behavior, and GPU compositing over an opaque
backdrop without relying on JavaScript upload-alpha changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 60c2ec68-6de1-445d-9fc9-b699db737eae
@bkaradzic-microsoft
bkaradzic-microsoft force-pushed the pr/canvas-gradient-interpolation branch from 3b2fc4f to 8b6e8f4 Compare September 18, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants