From 3997ab53ff947d67bfb81c4ac139ab441feeaa49 Mon Sep 17 00:00:00 2001 From: agustin-littlehat Date: Fri, 29 May 2026 07:52:14 -0300 Subject: [PATCH] fix(renderer): avoid baked preview paint on normal render --- .../polycss/src/api/createPolyScene.test.ts | 36 +++++++--- packages/polycss/src/api/createPolyScene.ts | 68 ++++++++----------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/packages/polycss/src/api/createPolyScene.test.ts b/packages/polycss/src/api/createPolyScene.test.ts index c4e74dcb..7ac6eac3 100644 --- a/packages/polycss/src/api/createPolyScene.test.ts +++ b/packages/polycss/src/api/createPolyScene.test.ts @@ -1331,6 +1331,17 @@ describe("createPolyScene", () => { expect(sceneEl.dataset.polycssLighting).toBe("baked"); }); + it("does not install baked preview paint vars during normal baked render", () => { + scene = makeScene(host, { textureLighting: "baked" }); + scene.add(makeParseResult([triangle("#336699")]), { merge: false }); + const leaf = host.querySelector("b, i, u") as HTMLElement; + + expect(leaf.style.color).not.toBe(""); + expect(leaf.style.getPropertyValue("--polycss-paint")).toBe(""); + expect(leaf.style.getPropertyValue("--plam")).toBe(""); + expect(leaf.style.getPropertyValue("--pnz")).toBe(""); + }); + it("can preview baked solid lighting through CSS vars without switching scene mode", () => { scene = makeScene(host, { textureLighting: "baked" }); scene.add(makeParseResult([triangle("#336699")]), { merge: false }); @@ -1338,7 +1349,6 @@ describe("createPolyScene", () => { const leaf = host.querySelector("b, i, u") as HTMLElement; const triangleLeaf = host.querySelector("u") as HTMLElement; const initialColor = leaf.style.color; - const initialLeafStyle = leaf.getAttribute("style"); const initialTriangleBackgroundColor = triangleLeaf.style.backgroundColor; const previewScene = scene as PolySceneHandle & { previewBakedSolidLighting(next: Pick): boolean; @@ -1357,8 +1367,7 @@ describe("createPolyScene", () => { expect(leaf.style.getPropertyValue("--plam")).toContain("var(--plz, 1)"); expect(leaf.style.getPropertyValue("--polycss-preview-r")).toContain("var(--plam, 0)"); expect(leaf.style.getPropertyValue("--polycss-paint")).toContain("var(--polycss-light-preview-active"); - expect(leaf.style.color).toBe(initialColor); - expect(leaf.getAttribute("style")).toBe(initialLeafStyle); + expect(leaf.style.color).toBe(""); expect(triangleLeaf.style.backgroundColor).toBe(initialTriangleBackgroundColor); previewScene.clearBakedSolidLightingPreview(); @@ -1366,8 +1375,9 @@ describe("createPolyScene", () => { expect(sceneEl.style.getPropertyValue("--plz")).toBe(""); expect(sceneEl.style.getPropertyValue("--polycss-light-preview-active")).toBe(""); expect(leaf.style.color).toBe(initialColor); - expect(leaf.style.getPropertyValue("--plam")).toContain("var(--plz, 1)"); - expect(leaf.style.getPropertyValue("--polycss-preview-r")).toContain("var(--plam, 0)"); + expect(leaf.style.getPropertyValue("--plam")).toBe(""); + expect(leaf.style.getPropertyValue("--polycss-preview-r")).toBe(""); + expect(leaf.style.getPropertyValue("--polycss-paint")).toBe(""); expect(triangleLeaf.style.backgroundColor).toBe(initialTriangleBackgroundColor); }); @@ -1377,6 +1387,7 @@ describe("createPolyScene", () => { const leaf = host.querySelector("b, i, u") as HTMLElement; const triangleLeaf = host.querySelector("u") as HTMLElement; const initialLeaf = leaf; + const initialColor = leaf.style.color; const initialTriangleBackgroundColor = triangleLeaf.style.backgroundColor; const previewScene = scene as PolySceneHandle & { previewBakedSolidLighting(next: Pick): boolean; @@ -1394,10 +1405,11 @@ describe("createPolyScene", () => { expect(previewScene.commitBakedSolidLighting()).toBe(true); expect(host.querySelector("b, i, u")).toBe(initialLeaf); - expect(leaf.style.color).toBe(""); - expect(leaf.style.getPropertyValue("--polycss-paint")).toContain("var(--polycss-light-preview-active"); - expect(leaf.style.getPropertyValue("--polycss-preview-r")).toContain("var(--plam, 0)"); - expect(leaf.style.getPropertyValue("--plam")).toContain("var(--plz, 1)"); + expect(leaf.style.color).not.toBe(""); + expect(leaf.style.color).not.toBe(initialColor); + expect(leaf.style.getPropertyValue("--polycss-paint")).toBe(""); + expect(leaf.style.getPropertyValue("--polycss-preview-r")).toBe(""); + expect(leaf.style.getPropertyValue("--plam")).toBe(""); expect(triangleLeaf.style.backgroundColor).toBe(initialTriangleBackgroundColor); }); @@ -1899,8 +1911,10 @@ describe("createPolyScene", () => { const after = host.querySelector("u, b, i, s") as HTMLElement; expect(after).toBe(before); expect(handle.polygons[0].color).toBe("#0000ff"); - expect(after.style.getPropertyValue("--polycss-paint")).not.toBe(""); - expect(after.style.getPropertyValue("--psb")).toBe("1.0000"); + expect(after.style.color).not.toBe(""); + expect(after.style.getPropertyValue("--polycss-paint")).toBe(""); + expect(after.style.getPropertyValue("--psb")).toBe(""); + expect(after.style.getPropertyValue("--plam")).toBe(""); }); it("updates data-only changes without replacing the leaf", () => { diff --git a/packages/polycss/src/api/createPolyScene.ts b/packages/polycss/src/api/createPolyScene.ts index 53a35c7b..aac9f36f 100644 --- a/packages/polycss/src/api/createPolyScene.ts +++ b/packages/polycss/src/api/createPolyScene.ts @@ -56,7 +56,6 @@ import { polygonCssSurfaceNormal, projectCssVertexToGround, parsePureColor, - shadePolygon, } from "@layoutit/polycss-core"; import { cssBorderShapeForPlan, @@ -989,7 +988,6 @@ export function createPolyScene( } entry.disposeAtlas = disposeAtlas; entry.solidLightingPreviewPrepared = false; - prepareBakedSolidLightingPreview(entry); } function renderedItemForPolygon(entry: MeshEntry, polygonIndex: number): RenderedPoly | undefined { @@ -1403,10 +1401,8 @@ export function createPolyScene( textureLighting, renderOptions, ); - if (textureLighting === "baked") { - return applyBakedSolidPreviewPaint(item, polygon, shaded.shadedColor); - } applySolidPaint(item.element, shaded, textureLighting); + if (textureLighting === "baked") clearBakedSolidPreviewPaintVars(item.element); return true; } @@ -1443,6 +1439,33 @@ export function createPolyScene( return changed; } + function clearBakedSolidPreviewPaintVars(el: HTMLElement): void { + el.style.removeProperty("--pnx"); + el.style.removeProperty("--pny"); + el.style.removeProperty("--pnz"); + el.style.removeProperty("--psr"); + el.style.removeProperty("--psg"); + el.style.removeProperty("--psb"); + el.style.removeProperty("--plam"); + el.style.removeProperty("--polycss-preview-r"); + el.style.removeProperty("--polycss-preview-g"); + el.style.removeProperty("--polycss-preview-b"); + el.style.removeProperty("--polycss-paint"); + } + + function restoreBakedSolidPaint(entry: MeshEntry): boolean { + let changed = false; + for (const item of entry.rendered) { + if (!item.plan || item.kind === "atlas" || item.plan.texture) continue; + const polygon = entry.polygons[item.polygonIndex]; + if (!polygon) continue; + changed = applyBakedSolidColor(item, polygon) || changed; + } + entry.solidLightingPreviewPrepared = false; + entry.solidLightingPreviewActive = false; + return changed; + } + function prepareBakedSolidLightingPreview(entry: MeshEntry): boolean { if ((currentOptions.textureLighting ?? "baked") !== "baked") return false; let prepared = false; @@ -1464,31 +1487,6 @@ export function createPolyScene( return true; } - function bakedSolidColorForPlan(item: RenderedPoly, polygon: Polygon): string { - const directionalCfg = currentOptions.directionalLight; - const ambientCfg = currentOptions.ambientLight; - const lightDir = directionalCfg?.direction ?? [0.4, -0.7, 0.59] as Vec3; - const lightColor = directionalCfg?.color ?? "#ffffff"; - const lightIntensity = Math.max(0, directionalCfg?.intensity ?? 1); - const ambientColor = ambientCfg?.color ?? "#ffffff"; - const ambientIntensity = Math.max(0, ambientCfg?.intensity ?? 0.4); - const lLen = Math.hypot(lightDir[0], lightDir[1], lightDir[2]) || 1; - const normal = item.plan!.normal; - const directScale = lightIntensity * Math.max( - 0, - normal[0] * (lightDir[0] / lLen) + - normal[1] * (lightDir[1] / lLen) + - normal[2] * (lightDir[2] / lLen), - ); - return shadePolygon( - polygon.color ?? "#cccccc", - directScale, - lightColor, - ambientColor, - ambientIntensity, - ); - } - function needsBakedAtlasCommit(item: RenderedPoly): boolean { return item.kind === "atlas" || !!item.plan?.texture; } @@ -1502,13 +1500,7 @@ export function createPolyScene( updated = true; continue; } - for (const item of entry.rendered) { - if (!item.plan || item.kind === "atlas" || item.plan.texture) continue; - const polygon = entry.polygons[item.polygonIndex]; - if (!polygon) continue; - const color = bakedSolidColorForPlan(item, polygon); - updated = applyBakedSolidPreviewPaint(item, polygon, color) || updated; - } + updated = restoreBakedSolidPaint(entry) || updated; } sceneEl.style.removeProperty(BAKED_SOLID_PREVIEW_ACTIVE_VAR); for (const entry of meshes) { @@ -1523,8 +1515,8 @@ export function createPolyScene( sceneEl.style.removeProperty(BAKED_SOLID_PREVIEW_ACTIVE_VAR); for (const entry of meshes) { if (!entry.solidLightingPreviewActive) continue; + restoreBakedSolidPaint(entry); clearLightingVars(entry.wrapper); - entry.solidLightingPreviewActive = false; } if ((currentOptions.textureLighting ?? "baked") !== "dynamic") { clearLightingVars(sceneEl);