Skip to content

Conversation

@donmccurdy
Copy link
Member

@donmccurdy donmccurdy commented Nov 20, 2025

Description

Texture coordinates are currently compressed to 12-bit precision, effectively on a 4096x4096 grid. Perhaps that could be revisited at some point, but in the meantime billboard-related code must be very careful with texture coordinates in large atlases. This PR makes two changes, intended to improve texture atlases along those lines:

  1. Atlases are now constrained to power-of-two dimensions on resize. By doing so we guarantee that the pixel grid aligns cleanly with the 4096x4096 grid used when quantizing texture coordinates.
  2. When resizing atlases, TextureAtlas.js now considers more candidate sizes, and in most cases should not allocate space in the atlas >>2x the requirement of the input images. Packing density, of course, is less predictable... but I haven't found egregious cases remaining after applying this fix.

Previously as current candidate atlas size became larger, the resize algorithm would use a larger multiplier to select the next candidate size, (2x, 4x, 8x, 16x, ...). In the particular case of #5154 this created a 2K-by-8K atlas, which required 16x more memory than required and (more visibly) flew past the 4096px limit at which Cesium's texture compression can precisely address pixels in the atlas.

Preview:

before after
Screenshot 2025-11-20 at 5 04 37 PM Screenshot 2025-11-20 at 5 05 19 PM

This PR should fully fix the cause of the clipped dots (•••) at the top of the icon. The unwanted vertical line visible on the left side of the icon happens to be somewhat improved by this PR, but that also has additional causes left for an upcoming PR.

Issue number and link

Testing plan

I'm looking through existing examples with one or more billboards. For each relevant example, compare computed texture atlas size before vs. after. Check that atlas size is "reasonable", i.e. not >> 2x the total area of the input images.

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

PR Dependency Tree

This tree was auto-generated by Charcoal

@github-actions
Copy link

Thank you for the pull request, @donmccurdy!

✅ We can confirm we have a CLA on file for you.

const areaDifference = areaQueued;
let scalingFactor = 1.0;
while (areaDifference / width / height >= 1.0) {
scalingFactor *= 2.0;
Copy link
Member Author

Choose a reason for hiding this comment

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

Since we'll have ... er, other challenges ... if the texture atlas size exceeds 16K x 16K, in practice this loop can't spend more than 28 iterations for the largest supportable atlas size. No need to use a sliding scale factor (which may cause us to miss more optimal atlas sizes) to save a small number of iterations.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants