Skip to content

Fix projective rendering for image source quads - #7903

Closed
i4innovationnet wants to merge 1 commit into
maplibre:mainfrom
i4innovationnet:fix/image-source-projective-raster
Closed

Fix projective rendering for image source quads#7903
i4innovationnet wants to merge 1 commit into
maplibre:mainfrom
i4innovationnet:fix/image-source-projective-raster

Conversation

@i4innovationnet

@i4innovationnet i4innovationnet commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Launch Checklist

  • Confirm your changes do not include backports from Mapbox projects (unless with compliant license) - if you are not sure about this, please ask!
  • Briefly describe the changes in this PR.
  • Link to related issues.
  • Include before/after visuals or gifs if this PR includes visual changes.
  • Write tests for all new functionality.
  • Document any changes to public APIs. No public API changes.
  • Post benchmark scores. Not applicable; no benchmark was run.
  • Add an entry to CHANGELOG.md under the ## main section.
  • Confirm you have read our AI policy here.

Summary

Fixes projective rendering for image source quads whose four coordinates do not form a parallelogram.

The raster shader now carries homogeneous texture coordinates for image, canvas, and video source quads and divides by the projective denominator in the fragment shader before sampling. Parallelogram quads and regular tiled raster sources keep affine behavior through an identity perspective transform.

ImageSource computes the complete inverse-homography denominator w = ax + by + c, rejects singular, non-finite, and zero-crossing transforms, and normalizes the homogeneous coefficients without assuming that c is nonzero. This preserves valid convex trapezoids while failing closed for degenerate, concave, and self-intersecting coordinates.

The texture correction remains separate from clip-space projection: projectTile owns gl_Position.w for Mercator, globe, and terrain paths, while this change performs the texture divide explicitly in the fragment shader.

Related Issue

Fixes #7886.

Visuals

The before screenshot and original reproduction are in #7886.

Render fixtures cover the corrected non-parallelogram case, a valid trapezoid whose homogeneous denominator has no constant term, and the projection modes discussed during review:

  • test/integration/render/tests/image/projective/style.json
  • test/integration/render/tests/image/projective-trapezoid/style.json
  • test/integration/render/tests/projection/globe/image-projective/style.json
  • test/integration/render/tests/terrain/image-projective/style.json

The projective fixtures use projective-grid.png and include semi-transparent vector outlines so the expected corner geometry remains visible.

Reviewer Follow-Up

  • Zoomed out the Mercator fixture so the complete image is visible.
  • Added semi-transparent vector outlines to the projective fixtures.
  • Added Mercator, globe, terrain, and zero-constant trapezoid render coverage.
  • Removed the test-only math export and raster-program plumbing test.
  • Kept the transform calculation and state in ImageSource; regular tiled raster sources explicitly pass identity coefficients.
  • Removed the unclear degenerate render fixture; numerical fallback behavior is covered through production ImageSource state tests.
  • Restored the raster-resampling fixture to local://image/0.png after reviewer consensus and regenerated its expected output.
  • Replaced the custom tolerance with Number.EPSILON-scaled singularity checks.
  • Converted the Heckbert source note to TSDoc with archive and PDF links.
  • Preserved valid homogeneous denominators with c = 0 and rejected denominators that reach or cross zero inside a quad.
  • Rebased onto current main and regenerated the combined bundle-size baseline.

Validation

Local validation on Node 24.11.1, after merging current main:

  • npm ci — 0 root-package vulnerabilities
  • npm run lint -- --max-warnings 0
  • npm run lint-css
  • npm run generate-typings
  • npm run typecheck
  • npm run generate-docs
  • npm run build-dist
  • npm run test-unit-ci — 196 files, 2,895 tests passed
  • npm run test-build-ci — 8 files, 699 tests passed
  • npm run test-integration-ci — 4 files, 176 tests passed
  • npm run test-render -- -t 'tests/(image/(projective|projective-trapezoid|default|raster-resampling)|projection/globe/image-projective|terrain/image-projective|canvas/default|video/default|raster-resampling/default)' — 9 affected render tests passed
  • git diff --check

The prior Windows integration failure was a Puppeteer navigation timeout in an untouched query-test setup path. It did not reproduce locally; the full integration suite passed twice after the production build prerequisite.

Assisted-By: OpenAI Codex (GPT-5)

Use homogeneous texture coordinates for non-parallelogram image, canvas, and video source quads across Mercator, globe, and terrain. Preserve valid zero-constant transforms, fall back for singular or zero-crossing denominators, and add unit and render coverage.

Fixes maplibre#7886.
@HarelM

HarelM commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

See my comment here about closing this one and opening the previous one:
#7887 (comment)

@i4innovationnet
i4innovationnet deleted the fix/image-source-projective-raster branch July 14, 2026 06:47
@i4innovationnet
i4innovationnet restored the fix/image-source-projective-raster branch July 14, 2026 06:47
@i4innovationnet

Copy link
Copy Markdown
Contributor Author

Closed in favor of the reopened #7887, preserving the original review conversation as requested. The verified commit is unchanged.

@i4innovationnet
i4innovationnet deleted the fix/image-source-projective-raster branch July 14, 2026 06:49
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.

ImageSource non-parallelogram quads render with diagonal affine texture seam

2 participants