Let a shader move the corners of the picture it wears (#79)
A shader could only say what colour a pixel has. Where the picture is drawn was fixed to the four corners of its rectangle, so nothing could wave, bend or wobble. - The new node Vertex output takes x and y, in pixels of the picture, and moves every corner of the wearer's grid by them. The UVs stay with the corners, so the picture bends along. - Subdivisions on that node says how fine the grid is: cells per axis, 1 to 64, 8 by default. 1 is the plain quad. A shader without the node keeps the quad every sprite shares. - A graph holds one Vertex output at most. UV, Time, Property, Number and the math nodes may feed it, and one node may feed both outputs. - Texture color, Texture alpha, Sample texture, Texture size and Color cannot feed it. The node says "Not available per corner" and the shader does not compile. - Sprites, texts and the preview in the shader tab wear the grid. A nine-slice sprite and particles draw as if the node were not there. - Picking, the selection frame, the size and colliders stay with the rectangle. A wearer with a Vertex output is never culled, as with Padding, and with Padding the grid covers the room around the picture too. - tools/perf-shaders.mjs takes GM_PERF_SUBDIVISIONS to measure a grid against the plain quad. Measured on stein2 (Intel HD 630), frames per second, one run per row: at 800 sprites 58 with a shader on the quad, 46 with 8 cells, 41 with 32. Up to 400 sprites a grid hardly shows. Every sprite holds its own grid. Tests: - Gate on melektaus-atx: 220 files, 3416 tests, CHECK EXIT 0. - 15 new unit tests for the compiler and the grid. - Four new e2e checks in modules 28 and 30: a fixed offset moves the picture, 8 cells bend only the lower half where 1 cell shears it all, Texture alpha is refused at the node, a text moves. - e2e 28,30 on melektaus-atx: 110 checks, all pass. - The e2e total of 1699 is counted (1695 + 4), the full suite did not run. - No counter-probe, no screenshot. Not looked at: the preview, Time in the browser, flipped sprites, Padding together with the grid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
963f8a152a
commit
4716726b6b
14 files changed
+586
-75
No files matched your search
@@ -33,6 +33,35 @@ export function paddedQuad(pad: QuadPadding): {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The same rectangle cut into `cells` by `cells` (#79), so a shader's Vertex output has corners to
|
||||
* move inside it. Positions and UVs stay one and the same, as on the quad.
|
||||
*/
|
||||
export function gridQuad(
|
||||
pad: QuadPadding | null,
|
||||
cells: number,
|
||||
): { positions: Float32Array; uvs: Float32Array; indices: Uint32Array } {
|
||||
const n = Math.max(1, Math.round(cells));
|
||||
const [u, v] = [pad?.u ?? 0, pad?.v ?? 0];
|
||||
const corners = new Float32Array((n + 1) * (n + 1) * 2);
|
||||
for (let row = 0; row <= n; row++) {
|
||||
for (let column = 0; column <= n; column++) {
|
||||
const at = (row * (n + 1) + column) * 2;
|
||||
corners[at] = -u + ((1 + 2 * u) * column) / n;
|
||||
corners[at + 1] = -v + ((1 + 2 * v) * row) / n;
|
||||
}
|
||||
}
|
||||
const indices = new Uint32Array(n * n * 6);
|
||||
for (let row = 0; row < n; row++) {
|
||||
for (let column = 0; column < n; column++) {
|
||||
const corner = row * (n + 1) + column;
|
||||
const below = corner + n + 1;
|
||||
indices.set([corner, corner + 1, below + 1, corner, below + 1, below], (row * n + column) * 6);
|
||||
}
|
||||
}
|
||||
return { positions: corners, uvs: new Float32Array(corners), indices };
|
||||
}
|
||||
|
||||
export function paddingKey(pad: QuadPadding | null): string {
|
||||
return pad ? `${pad.u},${pad.v}` : '';
|
||||
}
|
||||
Reference in new issue
Block a user