Skip to content
This repository was archived by the owner on May 19, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ Public API is **mirrored** across React and Vue. Adding a hook on one side witho
| Tag | Strategy | When chosen | Paint mechanism | Atlas memory |
|---|---|---|---|---|
| `<b>` | **Quads** | Axis-aligned rectangle, or untextured convex quad when the homography passes stability guards | `background: currentColor` on a fixed 64px rectangle; affine and projective quads normalize their `matrix3d` to that primitive, with tiny solid bleed on projective quads to overlap antialias seams | None |
| `<i>` | **Border-shape clipped solid** | Untextured non-rect on browsers with CSS `border-shape` (Chromium + `pointer:fine` + `hover:hover`) | `border-color: currentColor` on a fixed 16px border-shape primitive, clipped by `border-shape: polygon(...)`; polygon bbox scale and tiny solid bleed are folded into `matrix3d` | None |
| `<i>` | **Border-shape clipped solid** | Untextured non-rect on browsers with CSS `border-shape` (Chromium + `pointer:fine` + `hover:hover`) | `border-color: currentColor` on a fixed 64px border-shape primitive, clipped by `border-shape: polygon(...)`; polygon bbox scale and tiny solid bleed are folded into `matrix3d` | None |
| `<s>` | **Atlas slice** | Textured polygons, or untextured non-rect on browsers without `border-shape` | `background-image` slice of packed bitmap on a canonical 1px primitive; atlas position/size are normalized to the slice, scale lives in `matrix3d`, and shared textured edges get low-alpha atlas pixels repaired during atlas generation | Bounding-rect area |
| `<u>` | **Stable solid triangle** | Opt-in for triangles via `renderPolygonsWithStableTriangles` | CSS border-color triangle trick with a fixed canonical 1px border triangle; tiny solid bleed is folded into `matrix3d` | None |
| `<u>` | **Stable solid triangle** | Opt-in for triangles via `renderPolygonsWithStableTriangles` | CSS border-color triangle trick with a fixed canonical 64px border triangle; tiny solid bleed is folded into `matrix3d` | None |
| `<q>` | **Cast shadow leaf** | Per casting polygon when `castShadow: true` and dynamic lighting mode. Applies regardless of caster strategy — `<b>`/`<i>`/`<s>`/`<u>` all produce a `<q>` shadow because only the polygon's outline matters, not its surface. | Same `border-color: currentColor` + `border-shape: polygon(...)` as `<i>`, but transform composes `var(--shadow-proj)` to project the polygon onto the ground plane along the CSS-space light direction | None |

Strategies are ordered cheapest → most expensive. The mesher's job is to maximise `<b>` / `<i>` and minimise `<s>` (see "Meshing implications" below).
Expand Down
8 changes: 4 additions & 4 deletions packages/polycss/src/render/polyDOM.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,8 @@ describe("renderPolygonsWithTextureAtlas", () => {
const yScale = Math.hypot(matrix[4], matrix[5], matrix[6]);

expect(element.tagName.toLowerCase()).toBe("i");
expect(xScale).toBeGreaterThan(2 / 16);
expect(yScale).toBeGreaterThan(2 / 16);
expect(xScale).toBeGreaterThan(2 / 64);
expect(yScale).toBeGreaterThan(2 / 64);
expect(element.style.getPropertyValue("border-shape")).toContain("polygon(");
result.dispose();
});
Expand Down Expand Up @@ -610,10 +610,10 @@ describe("renderPolygonsWithTextureAtlas", () => {
expect(element.style.height).toBe("");
expect(element.style.getPropertyValue("--polycss-local-w")).toBe("");
expect(element.style.getPropertyValue("--polycss-local-h")).toBe("");
expect(matrix[0]).toBeGreaterThan(10 / 16);
expect(matrix[0]).toBeGreaterThan(10 / 64);
expect(matrix[1]).toBeCloseTo(0, 6);
expect(matrix[4]).toBeCloseTo(0, 6);
expect(matrix[5]).toBeGreaterThan(1 / 16);
expect(matrix[5]).toBeGreaterThan(1 / 64);
result.dispose();
});

Expand Down
10 changes: 6 additions & 4 deletions packages/polycss/src/render/textureAtlas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,10 @@ const DEFAULT_BORDER_SHAPE_DECIMALS = 2;
const DEFAULT_ATLAS_CSS_DECIMALS = 4;
const BORDER_SHAPE_CENTER_PERCENT = 50;
const BORDER_SHAPE_POINT_EPS = 1e-7;
const BORDER_SHAPE_CANONICAL_SIZE = 16;
const BORDER_SHAPE_CANONICAL_SIZE = 64;
const BORDER_SHAPE_BLEED = 0.9;
const QUAD_CANONICAL_SIZE = 64;
const SOLID_TRIANGLE_CANONICAL_SIZE = 64;
const PROJECTIVE_QUAD_DENOM_EPS = 0.05;
const PROJECTIVE_QUAD_MAX_WEIGHT_RATIO = Number.POSITIVE_INFINITY;
const PROJECTIVE_QUAD_BLEED = 0.6;
Expand Down Expand Up @@ -1749,12 +1750,13 @@ function computeSolidTrianglePlan(
baseLeft[1] - txCol[1],
baseLeft[2] - txCol[2],
];
const sourceSize = SOLID_TRIANGLE_CANONICAL_SIZE;
const canonicalMatrix = formatMatrix3dValues([
xCol[0], xCol[1], xCol[2], 0,
yCol[0], yCol[1], yCol[2], 0,
xCol[0] / sourceSize, xCol[1] / sourceSize, xCol[2] / sourceSize, 0,
yCol[0] / sourceSize, yCol[1] / sourceSize, yCol[2] / sourceSize, 0,
normal[0], normal[1], normal[2], 0,
txCol[0], txCol[1], txCol[2], 1,
]);
], 6);
const styleText = `transform:matrix3d(${canonicalMatrix});` +
bakedColor +
dynamicVars;
Expand Down
6 changes: 3 additions & 3 deletions packages/polycss/src/styles/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ const CORE_BASE_STYLES = `
}

.polycss-scene i {
width: 16px;
height: 16px;
width: 64px;
height: 64px;
border-color: currentColor;
}

Expand All @@ -100,7 +100,7 @@ const CORE_BASE_STYLES = `
box-sizing: content-box;
border: 0 solid transparent;
border-color: transparent transparent currentColor transparent;
border-width: 0 1px 1px 1px;
border-width: 0 64px 64px 64px;
}

/* <q> — dedicated shadow leaf. Same border-shape rendering trick as <i>
Expand Down
12 changes: 7 additions & 5 deletions packages/react/src/scene/textureAtlas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ const DEFAULT_BORDER_SHAPE_DECIMALS = 2;
const DEFAULT_ATLAS_CSS_DECIMALS = 4;
const BORDER_SHAPE_CENTER_PERCENT = 50;
const BORDER_SHAPE_POINT_EPS = 1e-7;
const BORDER_SHAPE_CANONICAL_SIZE = 16;
const BORDER_SHAPE_CANONICAL_SIZE = 64;
const QUAD_CANONICAL_SIZE = 64;
const SOLID_TRIANGLE_CANONICAL_SIZE = 64;
const PROJECTIVE_QUAD_DENOM_EPS = 0.05;
const PROJECTIVE_QUAD_MAX_WEIGHT_RATIO = 4;
const PROJECTIVE_QUAD_BLEED = 0.6;
const BASIS_EPS = 1e-9;
const SOLID_TRIANGLE_BLEED = 0.6;
const SOLID_TRIANGLE_BLEED = 0.75;

export type TextureQuality = number | "auto";

Expand Down Expand Up @@ -1018,12 +1019,13 @@ function solidTriangleStyle(
baseLeft[1] - txCol[1],
baseLeft[2] - txCol[2],
];
const sourceSize = SOLID_TRIANGLE_CANONICAL_SIZE;
const canonicalMatrix = formatMatrix3dValues([
xCol[0], xCol[1], xCol[2], 0,
yCol[0], yCol[1], yCol[2], 0,
xCol[0] / sourceSize, xCol[1] / sourceSize, xCol[2] / sourceSize, 0,
yCol[0] / sourceSize, yCol[1] / sourceSize, yCol[2] / sourceSize, 0,
normal[0], normal[1], normal[2], 0,
txCol[0], txCol[1], txCol[2], 1,
]);
], 6);
return {
transform: `matrix3d(${canonicalMatrix})`,
...sharedStyle,
Expand Down
6 changes: 3 additions & 3 deletions packages/react/src/styles/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ const CORE_BASE_STYLES = `
}

.polycss-scene i {
width: 16px;
height: 16px;
width: 64px;
height: 64px;
border-color: currentColor;
}

Expand All @@ -105,7 +105,7 @@ const CORE_BASE_STYLES = `
box-sizing: content-box;
border: 0 solid transparent;
border-color: transparent transparent currentColor transparent;
border-width: 0 1px 1px 1px;
border-width: 0 64px 64px 64px;
}

/* ── Gizmo override ─────────────────────────────────────────────────────── */
Expand Down
12 changes: 7 additions & 5 deletions packages/vue/src/scene/textureAtlas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ const DEFAULT_BORDER_SHAPE_DECIMALS = 2;
const DEFAULT_ATLAS_CSS_DECIMALS = 4;
const BORDER_SHAPE_CENTER_PERCENT = 50;
const BORDER_SHAPE_POINT_EPS = 1e-7;
const BORDER_SHAPE_CANONICAL_SIZE = 16;
const BORDER_SHAPE_CANONICAL_SIZE = 64;
const QUAD_CANONICAL_SIZE = 64;
const SOLID_TRIANGLE_CANONICAL_SIZE = 64;
const PROJECTIVE_QUAD_DENOM_EPS = 0.05;
const PROJECTIVE_QUAD_MAX_WEIGHT_RATIO = 4;
const PROJECTIVE_QUAD_BLEED = 0.6;
const BASIS_EPS = 1e-9;
const SOLID_TRIANGLE_BLEED = 0.6;
const SOLID_TRIANGLE_BLEED = 0.75;

export type TextureQuality = number | "auto";

Expand Down Expand Up @@ -1026,12 +1027,13 @@ function solidTriangleStyle(
baseLeft[1] - txCol[1],
baseLeft[2] - txCol[2],
];
const sourceSize = SOLID_TRIANGLE_CANONICAL_SIZE;
const canonicalMatrix = formatMatrix3dValues([
xCol[0], xCol[1], xCol[2], 0,
yCol[0], yCol[1], yCol[2], 0,
xCol[0] / sourceSize, xCol[1] / sourceSize, xCol[2] / sourceSize, 0,
yCol[0] / sourceSize, yCol[1] / sourceSize, yCol[2] / sourceSize, 0,
normal[0], normal[1], normal[2], 0,
txCol[0], txCol[1], txCol[2], 1,
]);
], 6);
return {
transform: `matrix3d(${canonicalMatrix})`,
...sharedStyle,
Expand Down
6 changes: 3 additions & 3 deletions packages/vue/src/styles/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ const CORE_BASE_STYLES = `
}

.polycss-scene i {
width: 16px;
height: 16px;
width: 64px;
height: 64px;
border-color: currentColor;
}

Expand All @@ -105,7 +105,7 @@ const CORE_BASE_STYLES = `
box-sizing: content-box;
border: 0 solid transparent;
border-color: transparent transparent currentColor transparent;
border-width: 0 1px 1px 1px;
border-width: 0 64px 64px 64px;
}

/* ── Dynamic lighting cascade vars (scene root → polygons) ─────────────── */
Expand Down
Loading