@flighthq/render-gl 0.3.0 → 0.3.1-next.1041.35b950c

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.
Files changed (39) hide show
  1. package/dist/enableGlRenderStateGuards.d.ts.map +1 -1
  2. package/dist/enableGlRenderStateGuards.js +12 -3
  3. package/dist/enableGlRenderStateGuards.js.map +1 -1
  4. package/dist/explainGlTextureResolution.d.ts.map +1 -1
  5. package/dist/explainGlTextureResolution.js +4 -1
  6. package/dist/explainGlTextureResolution.js.map +1 -1
  7. package/dist/glCompressedTexture.d.ts.map +1 -1
  8. package/dist/glCompressedTexture.js +13 -2
  9. package/dist/glCompressedTexture.js.map +1 -1
  10. package/dist/glDraw.d.ts.map +1 -1
  11. package/dist/glDraw.js +19 -12
  12. package/dist/glDraw.js.map +1 -1
  13. package/dist/glMaterialRegistry.d.ts.map +1 -1
  14. package/dist/glMaterialRegistry.js +13 -8
  15. package/dist/glMaterialRegistry.js.map +1 -1
  16. package/dist/glRenderState.d.ts +3 -1
  17. package/dist/glRenderState.d.ts.map +1 -1
  18. package/dist/glRenderState.js +53 -32
  19. package/dist/glRenderState.js.map +1 -1
  20. package/dist/glRenderStateBracket.d.ts.map +1 -1
  21. package/dist/glRenderStateBracket.js +54 -0
  22. package/dist/glRenderStateBracket.js.map +1 -1
  23. package/dist/glSkinPaletteTexture.d.ts +1 -1
  24. package/dist/glSkinPaletteTexture.d.ts.map +1 -1
  25. package/dist/glSkinPaletteTexture.js +6 -2
  26. package/dist/glSkinPaletteTexture.js.map +1 -1
  27. package/dist/glTextureResolver.d.ts.map +1 -1
  28. package/dist/glTextureResolver.js +13 -11
  29. package/dist/glTextureResolver.js.map +1 -1
  30. package/package.json +11 -10
  31. package/src/enableGlRenderStateGuards.test.ts +10 -0
  32. package/src/glCompressedTexture.test.ts +29 -12
  33. package/src/glDraw.test.ts +20 -1
  34. package/src/glMaterialRegistry.test.ts +16 -0
  35. package/src/glRenderState.test.ts +334 -25
  36. package/src/glRenderStateBracket.test.ts +170 -0
  37. package/src/glShader.test.ts +28 -0
  38. package/src/glTestHelper.test.ts +51 -0
  39. package/src/glTextureResolver.test.ts +11 -6
@@ -233,6 +233,34 @@ describe('setGlBaseUniforms', () => {
233
233
  });
234
234
 
235
235
  describe('setGlMatrixFromTransform', () => {
236
+ it('projects the quad corner order to a clockwise triangle, which is why 2D draws need culling off', () => {
237
+ // Measured in a real WebGL2 context, not argued: with CULL_FACE enabled and the CCW default, this
238
+ // quad renders 0 lit pixels where it otherwise renders 2304 — a single-sided 3D draw earlier in the
239
+ // frame therefore erases all 2D content. `renderGlScene2D` disables CULL_FACE because of THIS, and
240
+ // without an assertion the reason lives only in a comment: someone who later made the winding CCW
241
+ // would find the disable looking superfluous. The corner order below mirrors the quadVertexData
242
+ // fill in glDraw.ts and must be changed with it.
243
+ const gl = makeGL();
244
+ const m = new Float32Array(9);
245
+ const canvas = document.createElement('canvas');
246
+ canvas.width = 200;
247
+ canvas.height = 100;
248
+ setGlMatrixFromTransform(gl, makeShaderLoc(), m, { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }, canvas);
249
+
250
+ const project = (x: number, y: number): [number, number] => [
251
+ m[0] * x + m[3] * y + m[6],
252
+ m[1] * x + m[4] * y + m[7],
253
+ ];
254
+ const [x0, y0, x1, y1] = [20, 30, 120, 80];
255
+ const [ax, ay] = project(x0, y0);
256
+ const [bx, by] = project(x1, y0);
257
+ const [cx, cy] = project(x1, y1);
258
+
259
+ // Signed area of the first indexed triangle (indices [0, 1, 2]); negative is clockwise.
260
+ const signedArea = (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
261
+ expect(signedArea).toBeLessThan(0);
262
+ });
263
+
236
264
  it('computes matrix scaled by canvas dimensions for identity transform', () => {
237
265
  const gl = makeGL();
238
266
  const loc = makeShaderLoc();
@@ -0,0 +1,51 @@
1
+ import { makeGL } from './glTestHelper';
2
+
3
+ describe('makeGL', () => {
4
+ it('keeps draw validation outside a test-installed mock implementation', () => {
5
+ const gl = makeGL();
6
+ const draw = vi.fn();
7
+ (gl.drawElements as ReturnType<typeof vi.fn>).mockImplementation(draw);
8
+
9
+ gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 1);
10
+
11
+ expect(draw).not.toHaveBeenCalled();
12
+ expect(gl.getError()).toBe(gl.INVALID_OPERATION);
13
+
14
+ gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 0);
15
+ expect(draw).toHaveBeenCalledOnce();
16
+ });
17
+
18
+ it('sets and consumes the first GL draw error without throwing', () => {
19
+ const gl = makeGL();
20
+
21
+ expect(() => gl.drawElements(gl.TRIANGLES, -1, gl.UNSIGNED_SHORT, 0)).not.toThrow();
22
+ gl.drawElements(0xffff, 1, gl.UNSIGNED_SHORT, 0);
23
+
24
+ expect(gl.drawElements).not.toHaveBeenCalled();
25
+ expect(gl.getError()).toBe(gl.INVALID_VALUE);
26
+ expect(gl.getError()).toBe(gl.NO_ERROR);
27
+ });
28
+
29
+ it('reports a type-misaligned index offset as INVALID_OPERATION', () => {
30
+ const gl = makeGL();
31
+
32
+ gl.drawElements(gl.TRIANGLES, 1, gl.UNSIGNED_SHORT, 1);
33
+
34
+ expect(gl.getError()).toBe(gl.INVALID_OPERATION);
35
+ expect(gl.getError()).toBe(gl.NO_ERROR);
36
+ });
37
+
38
+ it('validates non-indexed and instanced draw entry points', () => {
39
+ const gl = makeGL();
40
+
41
+ gl.drawArrays(0xffff, 0, 1);
42
+ expect(gl.getError()).toBe(gl.INVALID_ENUM);
43
+
44
+ gl.drawArraysInstanced(gl.TRIANGLES, 0, 1, -1);
45
+ expect(gl.getError()).toBe(gl.INVALID_VALUE);
46
+
47
+ gl.drawElementsInstanced(gl.TRIANGLES, 1, gl.FLOAT, 0, 1);
48
+ expect(gl.getError()).toBe(gl.INVALID_ENUM);
49
+ expect(gl.getError()).toBe(gl.NO_ERROR);
50
+ });
51
+ });
@@ -1,4 +1,5 @@
1
1
  import { createEntity } from '@flighthq/entity/contract';
2
+ import { getRegistryTableKeys } from '@flighthq/registry/contract';
2
3
  import type { Image, RenderTexture, TextureLike, TextureSource } from '@flighthq/types/contract';
3
4
  import {
4
5
  BitmapTextureSourceKind,
@@ -80,11 +81,17 @@ function textureWithTarget(): TextureLike {
80
81
  return texture;
81
82
  }
82
83
 
84
+ function registeredTextureSourceKinds(state: Parameters<typeof getGlRenderStateRuntime>[0]): string[] {
85
+ const kinds: string[] = [];
86
+ getRegistryTableKeys(kinds, getGlRenderStateRuntime(state).registries.textureResolvers);
87
+ return kinds;
88
+ }
89
+
83
90
  describe('registerGlBitmapTextureResolver', () => {
84
91
  it('registers only the Bitmap source key', () => {
85
92
  const { state } = createGlState();
86
93
  registerGlBitmapTextureResolver(state);
87
- expect([...getGlRenderStateRuntime(state).glTextureResolverRegistry!.keys()]).toEqual([BitmapTextureSourceKind]);
94
+ expect(registeredTextureSourceKinds(state)).toEqual([BitmapTextureSourceKind]);
88
95
  });
89
96
  });
90
97
 
@@ -92,9 +99,7 @@ describe('registerGlCompressedImageTextureResolver', () => {
92
99
  it('registers only the CompressedImage source key', () => {
93
100
  const { state } = createGlState();
94
101
  registerGlCompressedImageTextureResolver(state);
95
- expect([...getGlRenderStateRuntime(state).glTextureResolverRegistry!.keys()]).toEqual([
96
- CompressedImageTextureSourceKind,
97
- ]);
102
+ expect(registeredTextureSourceKinds(state)).toEqual([CompressedImageTextureSourceKind]);
98
103
  });
99
104
  });
100
105
 
@@ -225,7 +230,7 @@ describe('registerGlTextureResolver', () => {
225
230
 
226
231
  registerGlTextureResolver(a, sourceKind, second);
227
232
  expect(resolveGlTexture(a, texture)).toEqual({ second: true });
228
- expect(getGlRenderStateRuntime(a).glTextureResolverRegistry?.size).toBe(1);
233
+ expect(getGlRenderStateRuntime(a).registries.textureResolvers.entries.size).toBe(1);
229
234
 
230
235
  registerGlTextureResolver(a, sourceKind, null);
231
236
  expect(resolveGlTexture(a, texture)).toBeNull();
@@ -244,7 +249,7 @@ describe('registerStandardGlTextureResolvers', () => {
244
249
  it('registers bitmap, image, and render texture sources without compressed images', () => {
245
250
  const { state } = createGlState();
246
251
  registerStandardGlTextureResolvers(state);
247
- expect([...getGlRenderStateRuntime(state).glTextureResolverRegistry!.keys()]).toEqual([
252
+ expect(registeredTextureSourceKinds(state)).toEqual([
248
253
  BitmapTextureSourceKind,
249
254
  ImageTextureSourceKind,
250
255
  RenderTargetTextureSourceKind,