@flighthq/render-gl 0.5.1-next.1059.c56d3cd → 0.5.1-next.1066.36fe89b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/render-gl`. The `@fl
|
|
|
13
13
|
This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
|
|
14
14
|
|
|
15
15
|
- [Flight project](https://github.com/flighthq/flight)
|
|
16
|
-
- [Source for @flighthq/render-gl@0.5.1-next.
|
|
17
|
-
- [License](https://github.com/flighthq/flight/blob/
|
|
16
|
+
- [Source for @flighthq/render-gl@0.5.1-next.1066.36fe89b](https://github.com/flighthq/flight/tree/36fe89ba6c64ce8afd3d789f17c5d9730a46f50f/packages/render-gl)
|
|
17
|
+
- [License](https://github.com/flighthq/flight/blob/36fe89ba6c64ce8afd3d789f17c5d9730a46f50f/LICENSE.md)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glSkinPaletteTexture.d.ts","sourceRoot":"","sources":["../src/glSkinPaletteTexture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASpG,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,SAAS,GAAG,oBAAoB,CAI9E;AAID,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAExG;AAKD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CAGjH;AAQD,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,QAAQ,CAAC,YAAY,CAAC,EACrC,UAAU,EAAE,MAAM,EAClB,cAAc,SAAI,GACjB,IAAI,
|
|
1
|
+
{"version":3,"file":"glSkinPaletteTexture.d.ts","sourceRoot":"","sources":["../src/glSkinPaletteTexture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASpG,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,SAAS,GAAG,oBAAoB,CAI9E;AAID,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAExG;AAKD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,SAAS,GAAG,IAAI,CAGjH;AAQD,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,oBAAoB,EAC7B,aAAa,EAAE,QAAQ,CAAC,YAAY,CAAC,EACrC,UAAU,EAAE,MAAM,EAClB,cAAc,SAAI,GACjB,IAAI,CAoCN"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
|
|
2
2
|
// The GPU skinning bone-palette data texture: the per-mesh joint-matrix palette in an RGBA32F texture
|
|
3
3
|
// the vertex shader reads with texelFetch (GLSL ES 3.0 core), one mat4 packed as four consecutive
|
|
4
|
-
// RGBA32F texels.
|
|
5
|
-
//
|
|
6
|
-
// MAX_TEXTURE_SIZE
|
|
7
|
-
//
|
|
4
|
+
// RGBA32F texels. When the total texel count fits within MAX_TEXTURE_SIZE, the palette is a single row
|
|
5
|
+
// (height 1); beyond that it wraps into multiple rows so the joint/instance count is bounded by
|
|
6
|
+
// MAX_TEXTURE_SIZE² rather than MAX_TEXTURE_SIZE. The vertex shader discovers the row width via
|
|
7
|
+
// textureSize() and computes 2D coordinates as ivec2(x % w, x / w).
|
|
8
8
|
export function createGlSkinPaletteTexture(gl) {
|
|
9
9
|
const out = allocateEntity();
|
|
10
10
|
initializeGlSkinPaletteTexture(out, gl);
|
|
@@ -33,12 +33,21 @@ export function uploadGlSkinPaletteTexture(gl, palette, jointMatrices, jointCoun
|
|
|
33
33
|
// rather than duplicated so both palettes share one upload path and cannot drift in how they grow,
|
|
34
34
|
// filter or clamp — a normal palette that wrapped or filtered would corrupt lighting exactly as a
|
|
35
35
|
// pose palette would, and the reasons not to are identical.
|
|
36
|
-
const
|
|
36
|
+
const totalTexels = jointCount * texelsPerJoint;
|
|
37
37
|
gl.bindTexture(gl.TEXTURE_2D, palette.texture);
|
|
38
38
|
// Raw float data — premultiply must be off. The image upload path leaves it on (sticky state).
|
|
39
39
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
40
40
|
if (jointCount > palette.jointCapacity) {
|
|
41
|
-
|
|
41
|
+
const maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);
|
|
42
|
+
const width = Math.min(totalTexels, maxWidth);
|
|
43
|
+
const height = Math.ceil(totalTexels / width);
|
|
44
|
+
if (height === 1) {
|
|
45
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, width, 1, 0, gl.RGBA, gl.FLOAT, jointMatrices);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA32F, width, height, 0, gl.RGBA, gl.FLOAT, null);
|
|
49
|
+
uploadGlPaletteTextureRows(gl, jointMatrices, totalTexels, width, height);
|
|
50
|
+
}
|
|
42
51
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
43
52
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
44
53
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
@@ -46,7 +55,24 @@ export function uploadGlSkinPaletteTexture(gl, palette, jointMatrices, jointCoun
|
|
|
46
55
|
palette.jointCapacity = jointCount;
|
|
47
56
|
}
|
|
48
57
|
else {
|
|
49
|
-
|
|
58
|
+
const maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);
|
|
59
|
+
const allocatedTexels = palette.jointCapacity * texelsPerJoint;
|
|
60
|
+
const width = Math.min(allocatedTexels, maxWidth);
|
|
61
|
+
if (totalTexels <= width) {
|
|
62
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, totalTexels, 1, gl.RGBA, gl.FLOAT, jointMatrices);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const height = Math.ceil(totalTexels / width);
|
|
66
|
+
uploadGlPaletteTextureRows(gl, jointMatrices, totalTexels, width, height);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function uploadGlPaletteTextureRows(gl, data, totalTexels, width, height) {
|
|
71
|
+
for (let y = 0; y < height; y++) {
|
|
72
|
+
const rowStart = y * width;
|
|
73
|
+
const rowTexels = Math.min(width, totalTexels - rowStart);
|
|
74
|
+
const floatStart = rowStart * 4;
|
|
75
|
+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, y, rowTexels, 1, gl.RGBA, gl.FLOAT, data.subarray(floatStart, floatStart + rowTexels * 4));
|
|
50
76
|
}
|
|
51
77
|
}
|
|
52
78
|
//# sourceMappingURL=glSkinPaletteTexture.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glSkinPaletteTexture.js","sourceRoot":"","sources":["../src/glSkinPaletteTexture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzE,sGAAsG;AACtG,kGAAkG;AAClG,
|
|
1
|
+
{"version":3,"file":"glSkinPaletteTexture.js","sourceRoot":"","sources":["../src/glSkinPaletteTexture.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/render-gl",
|
|
3
|
-
"version": "0.5.1-next.
|
|
3
|
+
"version": "0.5.1-next.1066.36fe89b",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/color": "0.5.1-next.
|
|
42
|
-
"@flighthq/entity": "0.5.1-next.
|
|
43
|
-
"@flighthq/log": "0.5.1-next.
|
|
44
|
-
"@flighthq/scene2d": "0.5.1-next.
|
|
45
|
-
"@flighthq/geometry": "0.5.1-next.
|
|
46
|
-
"@flighthq/render": "0.5.1-next.
|
|
47
|
-
"@flighthq/registry": "0.5.1-next.
|
|
48
|
-
"@flighthq/signals": "0.5.1-next.
|
|
49
|
-
"@flighthq/texture": "0.5.1-next.
|
|
50
|
-
"@flighthq/types": "0.5.1-next.
|
|
41
|
+
"@flighthq/color": "0.5.1-next.1066.36fe89b",
|
|
42
|
+
"@flighthq/entity": "0.5.1-next.1066.36fe89b",
|
|
43
|
+
"@flighthq/log": "0.5.1-next.1066.36fe89b",
|
|
44
|
+
"@flighthq/scene2d": "0.5.1-next.1066.36fe89b",
|
|
45
|
+
"@flighthq/geometry": "0.5.1-next.1066.36fe89b",
|
|
46
|
+
"@flighthq/render": "0.5.1-next.1066.36fe89b",
|
|
47
|
+
"@flighthq/registry": "0.5.1-next.1066.36fe89b",
|
|
48
|
+
"@flighthq/signals": "0.5.1-next.1066.36fe89b",
|
|
49
|
+
"@flighthq/texture": "0.5.1-next.1066.36fe89b",
|
|
50
|
+
"@flighthq/types": "0.5.1-next.1066.36fe89b"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"typescript": "^5.3.0"
|
|
@@ -12,7 +12,7 @@ interface Call {
|
|
|
12
12
|
args: unknown[];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function makeGl(): { gl: WebGL2RenderingContext; calls: Call[] } {
|
|
15
|
+
function makeGl(maxTextureSize = 4096): { gl: WebGL2RenderingContext; calls: Call[] } {
|
|
16
16
|
const calls: Call[] = [];
|
|
17
17
|
const record =
|
|
18
18
|
(name: string, result?: unknown) =>
|
|
@@ -21,6 +21,7 @@ function makeGl(): { gl: WebGL2RenderingContext; calls: Call[] } {
|
|
|
21
21
|
return result;
|
|
22
22
|
};
|
|
23
23
|
const gl = {
|
|
24
|
+
MAX_TEXTURE_SIZE: 0x0d33,
|
|
24
25
|
TEXTURE_2D: 0x0de1,
|
|
25
26
|
RGBA: 0x1908,
|
|
26
27
|
RGBA32F: 0x8814,
|
|
@@ -35,6 +36,11 @@ function makeGl(): { gl: WebGL2RenderingContext; calls: Call[] } {
|
|
|
35
36
|
createTexture: record('createTexture', { id: 'tex' }),
|
|
36
37
|
deleteTexture: record('deleteTexture'),
|
|
37
38
|
bindTexture: record('bindTexture'),
|
|
39
|
+
getParameter: (pname: number) => {
|
|
40
|
+
calls.push({ name: 'getParameter', args: [pname] });
|
|
41
|
+
if (pname === 0x0d33) return maxTextureSize;
|
|
42
|
+
return 0;
|
|
43
|
+
},
|
|
38
44
|
texImage2D: record('texImage2D'),
|
|
39
45
|
texSubImage2D: record('texSubImage2D'),
|
|
40
46
|
pixelStorei: record('pixelStorei'),
|
|
@@ -152,4 +158,42 @@ describe('uploadGlSkinPaletteTexture', () => {
|
|
|
152
158
|
uploadGlSkinPaletteTexture(gl, palette, makePalette(6), 6);
|
|
153
159
|
expect(palette.jointCapacity).toBe(6);
|
|
154
160
|
});
|
|
161
|
+
|
|
162
|
+
it('wraps into multiple rows when totalTexels exceeds MAX_TEXTURE_SIZE', () => {
|
|
163
|
+
const { gl, calls } = makeGl(16);
|
|
164
|
+
const palette = createGlSkinPaletteTexture(gl);
|
|
165
|
+
// 5 joints × 4 texels = 20 texels, max width 16 → 16 × 2 texture
|
|
166
|
+
uploadGlSkinPaletteTexture(gl, palette, makePalette(5), 5);
|
|
167
|
+
|
|
168
|
+
const alloc = calls.find((c) => c.name === 'texImage2D');
|
|
169
|
+
expect(alloc).toBeDefined();
|
|
170
|
+
expect(alloc?.args[3]).toBe(16); // width = MAX_TEXTURE_SIZE
|
|
171
|
+
expect(alloc?.args[4]).toBe(2); // height = ceil(20 / 16)
|
|
172
|
+
expect(alloc?.args[8]).toBeNull(); // allocated with null, then filled row by row
|
|
173
|
+
expect(palette.jointCapacity).toBe(5);
|
|
174
|
+
|
|
175
|
+
const subs = calls.filter((c) => c.name === 'texSubImage2D');
|
|
176
|
+
expect(subs.length).toBe(2);
|
|
177
|
+
expect(subs[0].args[3]).toBe(0); // row 0 yoffset
|
|
178
|
+
expect(subs[0].args[4]).toBe(16); // row 0 width = full row
|
|
179
|
+
expect(subs[1].args[3]).toBe(1); // row 1 yoffset
|
|
180
|
+
expect(subs[1].args[4]).toBe(4); // row 1 width = 20 - 16 remaining texels
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('uploads multi-row sub-image when data fits existing multi-row capacity', () => {
|
|
184
|
+
const { gl, calls } = makeGl(16);
|
|
185
|
+
const palette = createGlSkinPaletteTexture(gl);
|
|
186
|
+
// Allocate for 6 joints (24 texels → 16 × 2)
|
|
187
|
+
uploadGlSkinPaletteTexture(gl, palette, makePalette(6), 6);
|
|
188
|
+
calls.length = 0;
|
|
189
|
+
|
|
190
|
+
// Upload 5 joints (20 texels) into the existing 16 × 2 texture
|
|
191
|
+
uploadGlSkinPaletteTexture(gl, palette, makePalette(5), 5);
|
|
192
|
+
|
|
193
|
+
expect(calls.some((c) => c.name === 'texImage2D')).toBe(false);
|
|
194
|
+
const subs = calls.filter((c) => c.name === 'texSubImage2D');
|
|
195
|
+
expect(subs.length).toBe(2);
|
|
196
|
+
expect(subs[0].args[4]).toBe(16); // row 0 full width
|
|
197
|
+
expect(subs[1].args[4]).toBe(4); // row 1 partial (20 - 16)
|
|
198
|
+
});
|
|
155
199
|
});
|