@forgeax/engine-runtime 0.1.20 → 0.1.23
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 +105 -3
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts +2 -0
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts.map +1 -0
- package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
- package/dist/__tests__/helpers/register-scene-components.d.ts.map +1 -1
- package/dist/__tests__/lights-preservation.fixup.test.d.ts +2 -0
- package/dist/__tests__/lights-preservation.fixup.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/dist/sprite-param-values.d.ts +1 -1
- package/package.json +30 -30
- package/src/__tests__/active-camera.unit.test.ts +6 -8
- package/src/__tests__/animation-graph-asset-union.test-d.ts +2 -0
- package/src/__tests__/asset-brand-and-name-retirement.test.ts +4 -3
- package/src/__tests__/asset-registry-scene.test-d.ts +1 -0
- package/src/__tests__/asset-registry.recursive.spec.ts +1 -1
- package/src/__tests__/asset.unit.test.ts +5 -2
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +2 -2
- package/src/__tests__/collect-transient-roundtrip.test.ts +14 -3
- package/src/__tests__/components.test-d.ts +19 -9
- package/src/__tests__/components.unit.test.ts +36 -26
- package/src/__tests__/create-renderer-assembly.integration.test.ts +24 -0
- package/src/__tests__/create-renderer-gpu-pass-timing.unit.test.ts +32 -0
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +66 -0
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +9 -1
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +15 -2
- package/src/__tests__/errors.unit.test.ts +54 -20
- package/src/__tests__/extract-frames-merge.test.ts +51 -40
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +6 -2
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +13 -0
- package/src/__tests__/geometry.unit.test.ts +7 -10
- package/src/__tests__/helpers/register-runtime-components.ts +9 -1
- package/src/__tests__/helpers/register-scene-components.ts +9 -2
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +10 -11
- package/src/__tests__/light-snapshot.test-d.ts +35 -1
- package/src/__tests__/lights-preservation.fixup.test.ts +125 -0
- package/src/__tests__/lights.unit.test.ts +223 -308
- package/src/__tests__/loader-name-survival.test.ts +8 -9
- package/src/__tests__/package-promotion.test.ts +7 -11
- package/src/__tests__/pbr-pipeline.unit.test.ts +22 -17
- package/src/__tests__/pipeline.unit.test.ts +68 -226
- package/src/__tests__/point-light-shadow.browser.test.ts +209 -83
- package/src/__tests__/point-light-shadow.unit.test.ts +24 -47
- package/src/__tests__/propagate-transforms.dawn.test.ts +15 -16
- package/src/__tests__/record-worldid-isolation.test.ts +16 -32
- package/src/__tests__/render-error-exhaustive.test-d.ts +73 -9
- package/src/__tests__/render-system-extract.test.ts +5 -5
- package/src/__tests__/render-system-mega.test.ts +30 -41
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +5 -1
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +5 -1
- package/src/__tests__/render-system-skin-bg.unit.test.ts +14 -9
- package/src/__tests__/renderer-recover.unit.test.ts +8 -0
- package/src/__tests__/renderer-surface.unit.test.ts +229 -5
- package/src/__tests__/resolveName-unified-entry.test.ts +6 -6
- package/src/__tests__/resolveName.test.ts +14 -2
- package/src/__tests__/shadow-csm-atlas.test.ts +41 -0
- package/src/__tests__/shadow-csm-cascade-loadop.test.ts +1 -0
- package/src/__tests__/shadow-csm-component.test.ts +31 -24
- package/src/__tests__/shadow-csm-extract.test.ts +156 -47
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +72 -0
- package/src/__tests__/shadow-csm-shader.dawn.test.ts +19 -0
- package/src/__tests__/shadow-csm-tile-consistency.test.ts +1 -0
- package/src/__tests__/shadow-csm-ubo.test.ts +43 -45
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +29 -0
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +100 -24
- package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +1 -1
- package/src/__tests__/skin-parented-double-transform.test.ts +5 -5
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +4 -7
- package/src/__tests__/skylight-lazy-projection.test.ts +8 -5
- package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +11 -13
- package/src/__tests__/ssao-bgl.test.ts +12 -17
- package/src/__tests__/ssao-passes.test.ts +19 -2
- package/src/__tests__/systems.unit.test.ts +69 -205
- package/src/__tests__/template-game-default-api-contract.test.ts +45 -23
- package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +10 -4
- package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +2 -2
- package/src/__tests__/view-ubo-layout.browser.test.ts +20 -10
- package/src/collect-scene-asset.ts +1 -1
- package/src/components/__tests__/transform-vec-schema.test.ts +2 -2
- package/src/createRenderer.ts +2 -0
- package/src/index.ts +1 -2
- package/src/sprite-param-values.ts +1 -1
- package/dist/.tsbuildinfo +0 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { World } from '@forgeax/engine-ecs';
|
|
2
|
+
import { vec3 } from '@forgeax/engine-math';
|
|
3
|
+
import { Camera, PointLight, SpotLight } from '@forgeax/engine-render';
|
|
4
|
+
import { Transform } from '@forgeax/engine-scene';
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import {
|
|
7
|
+
computeInvRangeSquared,
|
|
8
|
+
degToCos,
|
|
9
|
+
validatePointLightShadowData,
|
|
10
|
+
validateSpotLightData,
|
|
11
|
+
} from '../../../render/src/components/light-helpers';
|
|
12
|
+
import { packDirectLightSlot } from '../../../render/src/light-buffer-layout';
|
|
13
|
+
import { buildPbrViewBglEntries } from '../../../render/src/pbr-pipeline';
|
|
14
|
+
import type {
|
|
15
|
+
PointLightSnapshot,
|
|
16
|
+
SpotLightSnapshot,
|
|
17
|
+
} from '../../../render/src/render-system-extract';
|
|
18
|
+
import { extractFrame, prepareExtractContext } from '../../../render/src/render-system-extract';
|
|
19
|
+
|
|
20
|
+
function pointSnapshot(): PointLightSnapshot {
|
|
21
|
+
return {
|
|
22
|
+
kind: 'point',
|
|
23
|
+
position: vec3.create(1, 2, 3),
|
|
24
|
+
color: vec3.create(2, 1, 0.5),
|
|
25
|
+
intensity: 2,
|
|
26
|
+
invRangeSquared: 0.25,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function spotSnapshot(): SpotLightSnapshot {
|
|
31
|
+
return {
|
|
32
|
+
kind: 'spot',
|
|
33
|
+
position: vec3.create(1, 2, 3),
|
|
34
|
+
direction: vec3.create(0, -1, 0),
|
|
35
|
+
color: vec3.create(2, 1, 0.5),
|
|
36
|
+
intensity: 2,
|
|
37
|
+
invRangeSquared: 0.25,
|
|
38
|
+
cosInner: degToCos(15),
|
|
39
|
+
cosOuter: degToCos(30),
|
|
40
|
+
castShadow: false,
|
|
41
|
+
lightViewProj: undefined,
|
|
42
|
+
mapSize: 512,
|
|
43
|
+
nearPlane: 0.1,
|
|
44
|
+
farPlane: 25,
|
|
45
|
+
shadowAtlasTile: -1,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe('Point/Spot and shared-light regression guard', () => {
|
|
50
|
+
it('keeps extract facts for point range and spot cone in the shared light path', () => {
|
|
51
|
+
const world = new World();
|
|
52
|
+
const pointSpawn = world.spawn(
|
|
53
|
+
{ component: Transform, data: { pos: [1, 2, 3] } },
|
|
54
|
+
{ component: PointLight, data: { range: 2 } },
|
|
55
|
+
);
|
|
56
|
+
const spotSpawn = world.spawn(
|
|
57
|
+
{ component: Transform, data: { pos: [4, 5, 6] } },
|
|
58
|
+
{
|
|
59
|
+
component: SpotLight,
|
|
60
|
+
data: { direction: [0, -1, 0], range: 4, innerConeDeg: 15, outerConeDeg: 30 },
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
world.spawn(
|
|
64
|
+
{ component: Transform, data: {} },
|
|
65
|
+
{ component: Camera, data: { fov: Math.PI / 4, aspect: 1, near: 0.1, far: 100 } },
|
|
66
|
+
);
|
|
67
|
+
expect(pointSpawn.ok, JSON.stringify(pointSpawn)).toBe(true);
|
|
68
|
+
expect(spotSpawn.ok, JSON.stringify(spotSpawn)).toBe(true);
|
|
69
|
+
|
|
70
|
+
const lights = extractFrame(world, prepareExtractContext(world)).lights;
|
|
71
|
+
expect(lights.point).toHaveLength(1);
|
|
72
|
+
expect(lights.point[0]?.invRangeSquared).toBeCloseTo(0.25, 6);
|
|
73
|
+
expect(lights.spot).toHaveLength(1);
|
|
74
|
+
expect(lights.spot[0]?.cosInner).toBeCloseTo(degToCos(15), 6);
|
|
75
|
+
expect(lights.spot[0]?.cosOuter).toBeCloseTo(degToCos(30), 6);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('keeps attenuation and cone helpers as finite, shared semantic owners', () => {
|
|
79
|
+
expect(computeInvRangeSquared(2)).toBeCloseTo(0.25, 8);
|
|
80
|
+
expect(computeInvRangeSquared(0)).toBe(1e8);
|
|
81
|
+
expect(computeInvRangeSquared(Number.POSITIVE_INFINITY)).toBe(0);
|
|
82
|
+
expect(degToCos(0)).toBeCloseTo(1, 8);
|
|
83
|
+
expect(degToCos(60)).toBeCloseTo(0.5, 8);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('keeps Point/Spot packing in the shared DirectLightSlot owner', () => {
|
|
87
|
+
const point = pointSnapshot();
|
|
88
|
+
const spot = spotSnapshot();
|
|
89
|
+
const pointSlot = packDirectLightSlot({ ...point, shadowAtlasLayer: 2 });
|
|
90
|
+
const spotSlot = packDirectLightSlot(spot);
|
|
91
|
+
|
|
92
|
+
expect(pointSlot.byteLength).toBe(80);
|
|
93
|
+
expect(spotSlot.byteLength).toBe(80);
|
|
94
|
+
expect(new Uint32Array(pointSlot.buffer)[16]).toBe(0);
|
|
95
|
+
expect(new Uint32Array(pointSlot.buffer)[17]).toBe(2);
|
|
96
|
+
expect(new Uint32Array(spotSlot.buffer)[16]).toBe(1);
|
|
97
|
+
expect(new Uint32Array(spotSlot.buffer)[17]).toBe(0xffffffff);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('keeps the PBR view layout independent from cluster light storage capability', () => {
|
|
101
|
+
const storageBindings = buildPbrViewBglEntries({ storageBuffer: true });
|
|
102
|
+
const uniformBindings = buildPbrViewBglEntries({ storageBuffer: false });
|
|
103
|
+
expect(storageBindings.map((entry) => entry.binding)).toEqual(
|
|
104
|
+
uniformBindings.map((entry) => entry.binding),
|
|
105
|
+
);
|
|
106
|
+
// Local lights are consumed through the cluster payload in group(2). The
|
|
107
|
+
// shared view group therefore has no legacy direct-light storage/uniform
|
|
108
|
+
// entries at bindings 1/2, and its shape cannot drift with the capability
|
|
109
|
+
// route selected for the cluster buffers.
|
|
110
|
+
expect(storageBindings.find((entry) => entry.binding === 1)).toBeUndefined();
|
|
111
|
+
expect(storageBindings.find((entry) => entry.binding === 2)).toBeUndefined();
|
|
112
|
+
expect(uniformBindings.find((entry) => entry.binding === 1)).toBeUndefined();
|
|
113
|
+
expect(uniformBindings.find((entry) => entry.binding === 2)).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('keeps Point/Spot pcfKernelSize validation independent of Directional quality', () => {
|
|
117
|
+
expect(
|
|
118
|
+
validatePointLightShadowData({ mapSize: 512, nearPlane: 0.1, farPlane: 20, pcfKernelSize: 5 })
|
|
119
|
+
.ok,
|
|
120
|
+
).toBe(true);
|
|
121
|
+
expect(validateSpotLightData({ direction: [0, -1, 0], pcfKernelSize: 3 }).ok).toBe(true);
|
|
122
|
+
expect(validatePointLightShadowData({ pcfKernelSize: 2 }).ok).toBe(false);
|
|
123
|
+
expect(validateSpotLightData({ direction: [0, -1, 0], pcfKernelSize: 2 }).ok).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
});
|