@flighthq/render 0.3.0-next.906.07cea63 → 0.3.0
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/dist/contract.d.ts +6 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +6 -1
- package/dist/contract.js.map +1 -1
- package/dist/enableColorAdjustmentGuards.js +6 -6
- package/dist/enableColorAdjustmentGuards.js.map +1 -1
- package/dist/enableColorAdjustments.d.ts +4 -0
- package/dist/enableColorAdjustments.d.ts.map +1 -0
- package/dist/enableColorAdjustments.js +110 -0
- package/dist/enableColorAdjustments.js.map +1 -0
- package/dist/enableSceneRenderGuards.d.ts +22 -0
- package/dist/enableSceneRenderGuards.d.ts.map +1 -0
- package/dist/enableSceneRenderGuards.js +36 -0
- package/dist/enableSceneRenderGuards.js.map +1 -0
- package/dist/explainScene2DCoverage.d.ts +4 -0
- package/dist/explainScene2DCoverage.d.ts.map +1 -0
- package/dist/explainScene2DCoverage.js +57 -0
- package/dist/explainScene2DCoverage.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/renderProxy.d.ts.map +1 -1
- package/dist/renderProxy.js +34 -9
- package/dist/renderProxy.js.map +1 -1
- package/dist/renderRegistryGuards.d.ts +5 -0
- package/dist/renderRegistryGuards.d.ts.map +1 -0
- package/dist/renderRegistryGuards.js +87 -0
- package/dist/renderRegistryGuards.js.map +1 -0
- package/dist/renderRegistrySignals.d.ts +3 -0
- package/dist/renderRegistrySignals.d.ts.map +1 -0
- package/dist/renderRegistrySignals.js +19 -0
- package/dist/renderRegistrySignals.js.map +1 -0
- package/dist/renderState.d.ts +1 -0
- package/dist/renderState.d.ts.map +1 -1
- package/dist/renderState.js +26 -0
- package/dist/renderState.js.map +1 -1
- package/dist/renderTarget.d.ts +4 -2
- package/dist/renderTarget.d.ts.map +1 -1
- package/dist/renderTarget.js +52 -2
- package/dist/renderTarget.js.map +1 -1
- package/dist/renderTransform2d.d.ts.map +1 -1
- package/dist/renderTransform2d.js +4 -1
- package/dist/renderTransform2d.js.map +1 -1
- package/dist/renderer.d.ts +1 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +16 -0
- package/dist/renderer.js.map +1 -1
- package/dist/scene2dWorkingColorSpace.d.ts +3 -0
- package/dist/scene2dWorkingColorSpace.d.ts.map +1 -0
- package/dist/scene2dWorkingColorSpace.js +19 -0
- package/dist/scene2dWorkingColorSpace.js.map +1 -0
- package/dist/sceneRender.d.ts +6 -2
- package/dist/sceneRender.d.ts.map +1 -1
- package/dist/sceneRender.js +47 -13
- package/dist/sceneRender.js.map +1 -1
- package/package.json +15 -12
- package/src/enableColorAdjustmentGuards.test.ts +6 -4
- package/src/enableColorAdjustments.test.ts +233 -0
- package/src/enableSceneRenderGuards.test.ts +96 -0
- package/src/explainScene2DCoverage.test.ts +113 -0
- package/src/renderProxy.test.ts +142 -11
- package/src/renderQueue.test.ts +1 -1
- package/src/renderRegistryGuards.test.ts +94 -0
- package/src/renderRegistrySignals.test.ts +15 -0
- package/src/renderState.test.ts +16 -1
- package/src/renderTarget.test.ts +113 -5
- package/src/renderTransform2d.test.ts +15 -1
- package/src/renderViewport.test.ts +1 -1
- package/src/renderer.test.ts +44 -1
- package/src/scene2dWorkingColorSpace.test.ts +11 -0
- package/src/sceneRender.test.ts +75 -2
- package/dist/renderColorScaleBias.d.ts +0 -3
- package/dist/renderColorScaleBias.d.ts.map +0 -1
- package/dist/renderColorScaleBias.js +0 -21
- package/dist/renderColorScaleBias.js.map +0 -1
- package/src/renderColorScaleBias.test.ts +0 -53
package/src/sceneRender.test.ts
CHANGED
|
@@ -25,7 +25,15 @@ import {
|
|
|
25
25
|
setNodeLocalMatrix4,
|
|
26
26
|
} from '@flighthq/node/contract';
|
|
27
27
|
import { createMesh, createNode3D, Node3DKind, getNode3DWorldAlpha } from '@flighthq/scene3d/contract';
|
|
28
|
-
import type {
|
|
28
|
+
import type {
|
|
29
|
+
Mesh,
|
|
30
|
+
Skin,
|
|
31
|
+
Camera3D,
|
|
32
|
+
Material,
|
|
33
|
+
MeshGeometry,
|
|
34
|
+
Scene3DLightBlock,
|
|
35
|
+
Scene3DLightsLike,
|
|
36
|
+
} from '@flighthq/types/contract';
|
|
29
37
|
import {
|
|
30
38
|
SCENE_LIGHT_BLOCK_FLOATS,
|
|
31
39
|
SCENE_LIGHT_HEMISPHERE_OFFSET,
|
|
@@ -35,7 +43,7 @@ import {
|
|
|
35
43
|
import { describe, expect, it } from 'vitest';
|
|
36
44
|
|
|
37
45
|
import { createRenderState } from './renderState';
|
|
38
|
-
import { packScene3DLightBlock, prepareScene3DRender } from './sceneRender';
|
|
46
|
+
import { packScene3DLightBlock, prepareScene3DRender, setSkinnedMeshBoundsGuard } from './sceneRender';
|
|
39
47
|
|
|
40
48
|
function boundedBox(): MeshGeometry {
|
|
41
49
|
const geometry = createBoxMeshGeometry(2, 2, 2);
|
|
@@ -244,6 +252,31 @@ describe('prepareScene3DRender', () => {
|
|
|
244
252
|
expect(list.viewProjection.m[15]).not.toBe(1);
|
|
245
253
|
});
|
|
246
254
|
|
|
255
|
+
it('uses a draw-time viewport aspect without mutating the camera projection', () => {
|
|
256
|
+
const state = createRenderState();
|
|
257
|
+
const scene = createNode3D(Node3DKind);
|
|
258
|
+
const camera = frontCamera();
|
|
259
|
+
|
|
260
|
+
const tallXScale = prepareScene3DRender(state, scene, camera, emptyLights(), 0.5).viewProjection.m[0];
|
|
261
|
+
const wideXScale = prepareScene3DRender(state, scene, camera, emptyLights(), 2).viewProjection.m[0];
|
|
262
|
+
|
|
263
|
+
expect(tallXScale).toBeCloseTo(wideXScale * 4);
|
|
264
|
+
expect(camera.projection.kind).toBe('perspective');
|
|
265
|
+
if (camera.projection.kind === 'perspective') expect(camera.projection.aspect).toBe(1);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('consumes camera jitter in the prepared view-projection', () => {
|
|
269
|
+
const state = createRenderState();
|
|
270
|
+
const scene = createNode3D(Node3DKind);
|
|
271
|
+
const camera = frontCamera();
|
|
272
|
+
const baseXOffset = prepareScene3DRender(state, scene, camera, emptyLights()).viewProjection.m[8];
|
|
273
|
+
|
|
274
|
+
camera.jitter.x = 0.125;
|
|
275
|
+
const jitteredXOffset = prepareScene3DRender(state, scene, camera, emptyLights()).viewProjection.m[8];
|
|
276
|
+
|
|
277
|
+
expect(jitteredXOffset).toBeCloseTo(baseXOffset - 0.125);
|
|
278
|
+
});
|
|
279
|
+
|
|
247
280
|
it('culls a mesh placed far behind the camera', () => {
|
|
248
281
|
const state = createRenderState();
|
|
249
282
|
const scene = createNode3D(Node3DKind);
|
|
@@ -402,3 +435,43 @@ describe('prepareScene3DRender', () => {
|
|
|
402
435
|
expect(getNodeWorldMatrix4(mesh).m[12]).toBeCloseTo(3);
|
|
403
436
|
});
|
|
404
437
|
});
|
|
438
|
+
|
|
439
|
+
describe('setSkinnedMeshBoundsGuard', () => {
|
|
440
|
+
afterEach(() => setSkinnedMeshBoundsGuard(null));
|
|
441
|
+
|
|
442
|
+
// The seam keeps the message and the @flighthq/log dependency in the separately-importable guard
|
|
443
|
+
// module; the cull path only calls whatever is installed.
|
|
444
|
+
it('reports the skinned mesh that reached culling without posed bounds', () => {
|
|
445
|
+
const seen: Mesh[] = [];
|
|
446
|
+
setSkinnedMeshBoundsGuard((mesh) => seen.push(mesh as Mesh));
|
|
447
|
+
const state = createRenderState();
|
|
448
|
+
const scene = createNode3D(Node3DKind);
|
|
449
|
+
const mesh = createMesh(boundedBox(), [null]);
|
|
450
|
+
mesh.skin = {} as Skin;
|
|
451
|
+
addNodeChild(scene, mesh);
|
|
452
|
+
|
|
453
|
+
prepareScene3DRender(state, scene, frontCamera(), {
|
|
454
|
+
ambient: createAmbientLight(),
|
|
455
|
+
directional: createDirectionalLight(),
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
expect(seen).toEqual([mesh]);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
it('stops reporting once cleared with null', () => {
|
|
462
|
+
let calls = 0;
|
|
463
|
+
setSkinnedMeshBoundsGuard(() => (calls += 1));
|
|
464
|
+
const state = createRenderState();
|
|
465
|
+
const scene = createNode3D(Node3DKind);
|
|
466
|
+
const mesh = createMesh(boundedBox(), [null]);
|
|
467
|
+
mesh.skin = {} as Skin;
|
|
468
|
+
addNodeChild(scene, mesh);
|
|
469
|
+
const lights = { ambient: createAmbientLight(), directional: createDirectionalLight() };
|
|
470
|
+
|
|
471
|
+
prepareScene3DRender(state, scene, frontCamera(), lights);
|
|
472
|
+
setSkinnedMeshBoundsGuard(null);
|
|
473
|
+
prepareScene3DRender(state, scene, frontCamera(), lights);
|
|
474
|
+
|
|
475
|
+
expect(calls).toBe(1);
|
|
476
|
+
});
|
|
477
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderColorScaleBias.d.ts","sourceRoot":"","sources":["../src/renderColorScaleBias.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA4C,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAcnH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,WAAW,EACjB,WAAW,CAAC,EAAE,WAAW,GACxB,IAAI,CAON"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { getNodeRuntime } from '@flighthq/node/contract';
|
|
2
|
-
import { getRenderStateRuntime } from './renderState';
|
|
3
|
-
// Hands the node's resolved color adjustment to the render node. A node's color-adjustment stack
|
|
4
|
-
// (NodeRuntime.colorAdjustments) is fused once into the affine `resolvedColorScaleBias` cache by the
|
|
5
|
-
// set-accessors on change — never per frame — so this hot-path visitor is a single field read, identical
|
|
6
|
-
// in cost to reading the old `.colorScaleBias`. Non-inheriting: a node uses its own resolved value (or
|
|
7
|
-
// none → null). The value is the Adjustment-tier fold input; it is not a material and does not key the
|
|
8
|
-
// batch.
|
|
9
|
-
//
|
|
10
|
-
// Matrix-tier channel mixing travels through `resolvedColorMatrix`. A non-matrix operation that cannot
|
|
11
|
-
// be represented by either path leaves `colorAdjustmentsUnsupported` set, invoking the shakeable guard
|
|
12
|
-
// so unsupported adjustment data is reported rather than silently discarded.
|
|
13
|
-
export function updateRenderProxyColorScaleBias(state, data, _parentData) {
|
|
14
|
-
const runtime = getNodeRuntime(data.source);
|
|
15
|
-
data.colorScaleBias = runtime.resolvedColorScaleBias ?? null;
|
|
16
|
-
data.colorMatrix = runtime.resolvedColorMatrix ?? null;
|
|
17
|
-
if (runtime.colorAdjustmentsUnsupported) {
|
|
18
|
-
getRenderStateRuntime(state).colorAdjustmentUnsupportedGuard?.(state, data.source);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=renderColorScaleBias.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderColorScaleBias.js","sourceRoot":"","sources":["../src/renderColorScaleBias.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,iGAAiG;AACjG,qGAAqG;AACrG,yGAAyG;AACzG,uGAAuG;AACvG,uGAAuG;AACvG,SAAS;AACT,EAAE;AACF,uGAAuG;AACvG,uGAAuG;AACvG,6EAA6E;AAC7E,MAAM,UAAU,+BAA+B,CAC7C,KAAkB,EAClB,IAAiB,EACjB,WAAyB;IAEzB,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,MAAc,CAA8C,CAAC;IACjG,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,sBAAsB,IAAI,IAAI,CAAC;IAC7D,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI,CAAC;IACvD,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;QACxC,qBAAqB,CAAC,KAAK,CAAC,CAAC,+BAA+B,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,MAAoB,CAAC,CAAC;IACnG,CAAC;AACH,CAAC"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { createColorMatrixAdjustment, createTintAdjustment } from '@flighthq/adjustments/contract';
|
|
2
|
-
import { setNodeColorAdjustments } from '@flighthq/node/contract';
|
|
3
|
-
import { createDisplayObject, getNode2DRuntime } from '@flighthq/scene2d/contract';
|
|
4
|
-
import type { Renderable } from '@flighthq/types/contract';
|
|
5
|
-
|
|
6
|
-
import { updateRenderProxyColorScaleBias } from './renderColorScaleBias';
|
|
7
|
-
import { createRenderProxy } from './renderProxy';
|
|
8
|
-
import { createRenderState } from './renderState';
|
|
9
|
-
|
|
10
|
-
describe('updateRenderProxyColorScaleBias', () => {
|
|
11
|
-
it('resolves a node color-adjustment stack onto the render node as an affine ColorScaleBias', () => {
|
|
12
|
-
const state = createRenderState();
|
|
13
|
-
const node = createDisplayObject();
|
|
14
|
-
setNodeColorAdjustments(node, [createTintAdjustment(0x7f0000ff)]);
|
|
15
|
-
const data = createRenderProxy(state, node as unknown as Renderable);
|
|
16
|
-
updateRenderProxyColorScaleBias(state, data);
|
|
17
|
-
expect(data.colorScaleBias).not.toBeNull();
|
|
18
|
-
expect(data.colorScaleBias!.redScale).toBeCloseTo(0x7f / 255);
|
|
19
|
-
expect(data.colorScaleBias!.greenScale).toBe(0);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('resolves channel mixing onto the render node as a complete matrix', () => {
|
|
23
|
-
const state = createRenderState();
|
|
24
|
-
const node = createDisplayObject();
|
|
25
|
-
const matrix = [1, 0.5, 0, 0, 0.1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0];
|
|
26
|
-
setNodeColorAdjustments(node, [createColorMatrixAdjustment(matrix)]);
|
|
27
|
-
const data = createRenderProxy(state, node as unknown as Renderable);
|
|
28
|
-
updateRenderProxyColorScaleBias(state, data);
|
|
29
|
-
expect(data.colorMatrix).toEqual(matrix);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('resolves to null when the node carries no adjustments', () => {
|
|
33
|
-
const state = createRenderState();
|
|
34
|
-
const node = createDisplayObject();
|
|
35
|
-
const data = createRenderProxy(state, node as unknown as Renderable);
|
|
36
|
-
updateRenderProxyColorScaleBias(state, data);
|
|
37
|
-
expect(data.colorScaleBias).toBeNull();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('reads the cache the accessor fused once (the walk never re-fuses)', () => {
|
|
41
|
-
const state = createRenderState();
|
|
42
|
-
const node = createDisplayObject();
|
|
43
|
-
setNodeColorAdjustments(node, [createTintAdjustment(0x3fffffff)]);
|
|
44
|
-
// The set-accessor fused the stack once; the runtime already holds the cached resolved value.
|
|
45
|
-
const cached = getNode2DRuntime(node).resolvedColorScaleBias;
|
|
46
|
-
expect(cached).not.toBeNull();
|
|
47
|
-
const data = createRenderProxy(state, node as unknown as Renderable);
|
|
48
|
-
updateRenderProxyColorScaleBias(state, data);
|
|
49
|
-
expect(data.colorScaleBias).toBe(cached);
|
|
50
|
-
updateRenderProxyColorScaleBias(state, data);
|
|
51
|
-
expect(data.colorScaleBias).toBe(cached);
|
|
52
|
-
});
|
|
53
|
-
});
|