Compare commits

...

6 Commits

Author SHA1 Message Date
Jeshurun Hembd bf08019553
Merge 2d0e881db0 into ee2b3813b2 2025-11-21 12:20:03 -05:00
jjspace ee2b3813b2
Merge pull request #13038 from CesiumGS/fix/textureatlas-border-internal
deploy / deploy (push) Has been cancelled Details
dev / lint (push) Has been cancelled Details
dev / coverage (push) Has been cancelled Details
dev / release-tests (push) Has been cancelled Details
dev / node-20 (push) Has been cancelled Details
sandcastle-dev / deploy (push) Has been cancelled Details
fix(textureatlas): Apply internal padding between images
2025-11-21 17:14:38 +00:00
Don McCurdy 4e3980cc53 fix(textureatlas): Apply internal padding between images 2025-11-21 11:44:18 -05:00
Jeshurun Hembd 2d0e881db0 Update playwright config for new Chrome headless 2025-06-05 16:15:41 -04:00
Jeshurun Hembd b8ee60182e Revert GPU args in playwright launch config 2025-06-04 17:58:43 -04:00
Jeshurun Hembd e87a069808 Update playwright version, yargs syntax 2025-06-04 16:24:05 -04:00
7 changed files with 169 additions and 47 deletions

View File

@ -7,7 +7,8 @@
#### Fixes :wrench: #### Fixes :wrench:
- Billboards using `imageSubRegion` now render as expected. [#12585](https://github.com/CesiumGS/cesium/issues/12585) - Billboards using `imageSubRegion` now render as expected. [#12585](https://github.com/CesiumGS/cesium/issues/12585)
- Improved scaling of SVGs in billboards [#TODO](https://github.com/CesiumGS/cesium/issues/TODO) - Improved scaling of SVGs in billboards [#13020](https://github.com/CesiumGS/cesium/issues/13020)
- Fixed unexpected outline artifacts around billboards [#13038](https://github.com/CesiumGS/cesium/issues/13038)
#### Additions :tada: #### Additions :tada:

View File

@ -1,14 +1,16 @@
import { defineConfig, devices } from "@playwright/test"; import { defineConfig, devices } from "@playwright/test";
import yargs from "yargs"; import yargs from "yargs";
const argv = yargs(process.argv).options({ const argv = yargs(process.argv)
"update-snapshots": { .options({
alias: "u", "update-snapshots": {
description: "Update test snapshots.", alias: "u",
type: "boolean", description: "Update test snapshots.",
default: false, type: "boolean",
}, default: false,
}).argv; },
})
.parse();
const baseUrl = `http://localhost:3000`; const baseUrl = `http://localhost:3000`;
const updateSnapshots = argv["update-snapshots"]; const updateSnapshots = argv["update-snapshots"];
@ -53,10 +55,11 @@ export default defineConfig({
name: "chromium", name: "chromium",
use: { use: {
...devices["Desktop Chrome"], ...devices["Desktop Chrome"],
channel: "chromium",
viewport: defaultViewport, viewport: defaultViewport,
launchOptions: { launchOptions: {
// this forces chrome to use the gpu for webgl which greatly speeds up tests // this forces chrome to use the gpu for webgl which greatly speeds up tests
args: ["--use-angle=gl"], args: ["--use-angle=gl", "--enable-features=Vulkan"],
}, },
}, },
}, },

View File

@ -57,7 +57,7 @@ const noDevelopmentGallery =
taskName === "release" || taskName === "release" ||
taskName === "makeZip" || taskName === "makeZip" ||
taskName === "websiteRelease"; taskName === "websiteRelease";
const argv = yargs(process.argv).argv; const argv = yargs(process.argv).parse();
const verbose = argv.verbose; const verbose = argv.verbose;
const sourceFiles = [ const sourceFiles = [

View File

@ -56,7 +56,7 @@
}, },
"devDependencies": { "devDependencies": {
"@cesium/eslint-config": "^12.0.0", "@cesium/eslint-config": "^12.0.0",
"@playwright/test": "^1.41.1", "@playwright/test": "^1.52.0",
"chokidar": "^4.0.1", "chokidar": "^4.0.1",
"cloc": "^2.6.0-cloc", "cloc": "^2.6.0-cloc",
"compression": "^1.7.4", "compression": "^1.7.4",

View File

@ -122,6 +122,8 @@ TexturePacker.prototype._findNode = function (node, { width, height }) {
return node; return node;
} }
const borderPadding = this._borderPadding;
// Vertical split (childNode1 = left half, childNode2 = right half). // Vertical split (childNode1 = left half, childNode2 = right half).
if (widthDifference > heightDifference) { if (widthDifference > heightDifference) {
node.childNode1 = new TextureNode({ node.childNode1 = new TextureNode({
@ -130,12 +132,18 @@ TexturePacker.prototype._findNode = function (node, { width, height }) {
width, width,
height: nodeHeight, height: nodeHeight,
}); });
node.childNode2 = new TextureNode({
x: rectangle.x + width, // Apply padding only along the vertical "cut".
y: rectangle.y, const widthDifferencePadded = widthDifference - borderPadding;
width: widthDifference,
height: nodeHeight, if (widthDifferencePadded > 0) {
}); node.childNode2 = new TextureNode({
x: rectangle.x + width + borderPadding,
y: rectangle.y,
width: widthDifferencePadded,
height: nodeHeight,
});
}
return this._findNode(node.childNode1, { width, height }); return this._findNode(node.childNode1, { width, height });
} }
@ -147,12 +155,19 @@ TexturePacker.prototype._findNode = function (node, { width, height }) {
width: nodeWidth, width: nodeWidth,
height, height,
}); });
node.childNode2 = new TextureNode({
x: rectangle.x, // Apply padding only along the horizontal "cut".
y: rectangle.y + height, const heightDifferencePadded = heightDifference - borderPadding;
width: nodeWidth,
height: heightDifference, if (heightDifferencePadded > 0) {
}); node.childNode2 = new TextureNode({
x: rectangle.x,
y: rectangle.y + height + borderPadding,
width: nodeWidth,
height: heightDifferencePadded,
});
}
return this._findNode(node.childNode1, { width, height }); return this._findNode(node.childNode1, { width, height });
} }

View File

@ -852,16 +852,16 @@ describe("Scene/TextureAtlas", function () {
.2222222222222222............... .2222222222222222...............
.2222222222222222............... .2222222222222222...............
.2222222222222222............... .2222222222222222...............
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333....
.22222222222222223333333333..... .2222222222222222.3333333333.1..
.22222222222222223333333333..... .2222222222222222.3333333333....
.2222222222222222333333333301... .2222222222222222.3333333333.0..
................................ ................................
`.trim(), `.trim(),
); );
@ -926,9 +926,9 @@ describe("Scene/TextureAtlas", function () {
.2222222222... .2222222222...
.2222222222... .2222222222...
.2222222222... .2222222222...
.2222222222.1.
.2222222222... .2222222222...
.2222222222... .2222222222.0.
.222222222201.
.............. ..............
`.trim(), `.trim(),
); );
@ -976,16 +976,16 @@ describe("Scene/TextureAtlas", function () {
.3333333333333333............... .3333333333333333...............
.3333333333333333............... .3333333333333333...............
.3333333333333333............... .3333333333333333...............
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222....
.33333333333333332222222222..... .3333333333333333.2222222222.1..
.33333333333333332222222222..... .3333333333333333.2222222222....
.3333333333333333222222222201... .3333333333333333.2222222222.0..
................................ ................................
`.trim(), `.trim(),
); );
@ -1337,6 +1337,108 @@ describe("Scene/TextureAtlas", function () {
).contextToRender([0, 255, 0, 255]); ).contextToRender([0, 255, 0, 255]);
}); });
it("adds custom padding with borderWidthInPixels", async function () {
atlas = new TextureAtlas({ borderWidthInPixels: 0 });
let indices = await addImages();
expect(drawAtlas(atlas, indices)).toBe(
`
................
................
................
................
................
................
2222222222......
2222222222......
2222222222......
2222222222......
2222222222......
2222222222......
22222222220.....
22222222220.....
22222222220.....
222222222201....
`.trim(),
);
atlas = new TextureAtlas({ borderWidthInPixels: 2 });
indices = await addImages();
expect(drawAtlas(atlas, indices)).toBe(
`
................................
................................
................................
................................
..2222222222....................
..2222222222....................
..2222222222....................
..2222222222..1.................
..2222222222....................
..2222222222....................
..2222222222..0.................
..2222222222..0.................
..2222222222..0.................
..2222222222..0.................
................................
................................
`.trim(),
);
atlas = new TextureAtlas({ borderWidthInPixels: 5 });
indices = await addImages();
expect(drawAtlas(atlas, indices)).toBe(
`
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
................................
.....2222222222.................
.....2222222222.................
.....2222222222.................
.....2222222222.................
.....2222222222.................
.....2222222222.................
.....2222222222.....0...........
.....2222222222.....0...........
.....2222222222.....0...........
.....2222222222.....0.....1.....
................................
................................
................................
................................
................................
`.trim(),
);
async function addImages() {
const promise = Promise.all([
atlas.addImage(tallGreenGuid, tallGreenImage),
atlas.addImage(blueGuid, blueImage),
atlas.addImage(bigBlueGuid, bigBlueImage),
]);
return pollWhilePromise(promise, () => {
atlas.update(scene.frameState.context);
});
}
});
it("GUID changes when atlas texure is modified", async function () { it("GUID changes when atlas texure is modified", async function () {
atlas = new TextureAtlas(); atlas = new TextureAtlas();

View File

@ -37,7 +37,8 @@ const argv = yargs(process.argv)
description: "If true, skip build step and serve existing built files.", description: "If true, skip build step and serve existing built files.",
}, },
}) })
.help().argv; .help()
.parse();
// These functions will not exist in the production zip file but they also won't be run // These functions will not exist in the production zip file but they also won't be run
const { getSandcastleConfig, buildSandcastleGallery, buildSandcastleApp } = const { getSandcastleConfig, buildSandcastleGallery, buildSandcastleApp } =