@flighthq/render 0.1.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/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/renderAppearance.d.ts +3 -0
- package/dist/renderAppearance.d.ts.map +1 -0
- package/dist/renderAppearance.js +35 -0
- package/dist/renderAppearance.js.map +1 -0
- package/dist/renderCache.d.ts +36 -0
- package/dist/renderCache.d.ts.map +1 -0
- package/dist/renderCache.js +83 -0
- package/dist/renderCache.js.map +1 -0
- package/dist/renderColor.d.ts +3 -0
- package/dist/renderColor.d.ts.map +1 -0
- package/dist/renderColor.js +17 -0
- package/dist/renderColor.js.map +1 -0
- package/dist/renderMaterial.d.ts +3 -0
- package/dist/renderMaterial.d.ts.map +1 -0
- package/dist/renderMaterial.js +9 -0
- package/dist/renderMaterial.js.map +1 -0
- package/dist/renderProxy.d.ts +19 -0
- package/dist/renderProxy.d.ts.map +1 -0
- package/dist/renderProxy.js +203 -0
- package/dist/renderProxy.js.map +1 -0
- package/dist/renderProxyAdapter.d.ts +7 -0
- package/dist/renderProxyAdapter.d.ts.map +1 -0
- package/dist/renderProxyAdapter.js +32 -0
- package/dist/renderProxyAdapter.js.map +1 -0
- package/dist/renderQueue.d.ts +9 -0
- package/dist/renderQueue.d.ts.map +1 -0
- package/dist/renderQueue.js +97 -0
- package/dist/renderQueue.js.map +1 -0
- package/dist/renderState.d.ts +5 -0
- package/dist/renderState.d.ts.map +1 -0
- package/dist/renderState.js +42 -0
- package/dist/renderState.js.map +1 -0
- package/dist/renderTarget.d.ts +21 -0
- package/dist/renderTarget.d.ts.map +1 -0
- package/dist/renderTarget.js +39 -0
- package/dist/renderTarget.js.map +1 -0
- package/dist/renderTransform2d.d.ts +3 -0
- package/dist/renderTransform2d.d.ts.map +1 -0
- package/dist/renderTransform2d.js +26 -0
- package/dist/renderTransform2d.js.map +1 -0
- package/dist/renderViewport.d.ts +6 -0
- package/dist/renderViewport.d.ts.map +1 -0
- package/dist/renderViewport.js +57 -0
- package/dist/renderViewport.js.map +1 -0
- package/dist/renderer.d.ts +6 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +24 -0
- package/dist/renderer.js.map +1 -0
- package/dist/sceneRender.d.ts +4 -0
- package/dist/sceneRender.d.ts.map +1 -0
- package/dist/sceneRender.js +175 -0
- package/dist/sceneRender.js.map +1 -0
- package/package.json +48 -0
- package/src/renderAppearance.test.ts +109 -0
- package/src/renderCache.test.ts +151 -0
- package/src/renderColor.test.ts +10 -0
- package/src/renderMaterial.test.ts +30 -0
- package/src/renderProxy.test.ts +531 -0
- package/src/renderProxyAdapter.test.ts +101 -0
- package/src/renderQueue.test.ts +210 -0
- package/src/renderState.test.ts +93 -0
- package/src/renderTarget.test.ts +84 -0
- package/src/renderTransform2d.test.ts +59 -0
- package/src/renderViewport.test.ts +187 -0
- package/src/renderer.test.ts +128 -0
- package/src/sceneRender.test.ts +207 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { getNodeRuntime } from '@flighthq/node';
|
|
2
|
+
import { getRenderStateRuntime } from './renderState';
|
|
3
|
+
// Fills `out` by walking the prepared subtree rooted at `source` and pushing one entry per visible
|
|
4
|
+
// proxy with a renderer. The sort key is the scene-order index (order of encounter in a pre-order
|
|
5
|
+
// traversal), preserving scene-graph draw order when no reorder is needed. Call sortRenderQueue
|
|
6
|
+
// afterward to reorder by an explicit criterion such as opaque-front-to-back / alpha-back-to-front.
|
|
7
|
+
//
|
|
8
|
+
// Does not advance the frame id — the prepare pass has already done that. Call
|
|
9
|
+
// prepareDisplayObjectRender before buildRenderQueue.
|
|
10
|
+
export function buildRenderQueue(state, source, out) {
|
|
11
|
+
clearRenderQueue(out);
|
|
12
|
+
const runtime = getRenderStateRuntime(state);
|
|
13
|
+
const renderProxyMap = runtime.renderProxyMap;
|
|
14
|
+
const stack = _buildStack;
|
|
15
|
+
let stackLength = 1;
|
|
16
|
+
stack[0] = source;
|
|
17
|
+
let sceneOrder = 0;
|
|
18
|
+
while (stackLength > 0) {
|
|
19
|
+
const current = stack[--stackLength];
|
|
20
|
+
const proxy = renderProxyMap.get(current);
|
|
21
|
+
if (proxy === undefined)
|
|
22
|
+
continue;
|
|
23
|
+
if (!proxy.visible)
|
|
24
|
+
continue;
|
|
25
|
+
if (proxy.renderer !== null) {
|
|
26
|
+
pushRenderQueueEntry(out, proxy, sceneOrder);
|
|
27
|
+
}
|
|
28
|
+
sceneOrder++;
|
|
29
|
+
// A Renderable is a node or a RenderCache leaf; only nodes carry children, and a cache yields a
|
|
30
|
+
// null-children runtime, so it is safe to read children through the node runtime view.
|
|
31
|
+
const children = getNodeRuntime(current).children;
|
|
32
|
+
if (children !== null) {
|
|
33
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
34
|
+
stack[stackLength++] = children[i];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Clears the queue for reuse. Resets entryCount to 0 without releasing the entries array, so
|
|
40
|
+
// subsequent fills in the same frame reuse capacity without allocation.
|
|
41
|
+
export function clearRenderQueue(queue) {
|
|
42
|
+
queue.entryCount = 0;
|
|
43
|
+
}
|
|
44
|
+
// Default sort comparator: ascending by sort key (smaller key = drawn first).
|
|
45
|
+
export function compareRenderQueueEntries(a, b) {
|
|
46
|
+
return a.sortKey - b.sortKey;
|
|
47
|
+
}
|
|
48
|
+
// Creates a new empty RenderQueue. The entries array is pre-allocated empty; entries grow as
|
|
49
|
+
// pushRenderQueueEntry or buildRenderQueue populates it. Cleared between frames by clearRenderQueue.
|
|
50
|
+
export function createRenderQueue() {
|
|
51
|
+
return { entries: [], entryCount: 0 };
|
|
52
|
+
}
|
|
53
|
+
// Packs a layer index, a normalized depth (0..1), and an opaque flag into a single sort key
|
|
54
|
+
// float. Layer is the most-significant axis; within a layer, opaque geometry sorts before
|
|
55
|
+
// transparent (flag 0 < flag 1), and within that bucket depth is the tiebreaker.
|
|
56
|
+
//
|
|
57
|
+
// Layout (for integer arithmetic; packed into a number):
|
|
58
|
+
// bits [30..16]: layer (15-bit, 0..32767)
|
|
59
|
+
// bit [15]: isTransparent flag (0 = opaque, 1 = transparent)
|
|
60
|
+
// bits [14..0]: depth bucket (15-bit, 0..32767, derived from depth * 32767)
|
|
61
|
+
export function packRenderSortKey(layer, depth, isTransparent) {
|
|
62
|
+
const layerBits = (Math.max(0, Math.min(32767, layer | 0)) & 0x7fff) << 16;
|
|
63
|
+
const transparentBit = isTransparent ? 1 << 15 : 0;
|
|
64
|
+
const depthBits = Math.max(0, Math.min(32767, Math.round(depth * 32767))) & 0x7fff;
|
|
65
|
+
return layerBits | transparentBit | depthBits;
|
|
66
|
+
}
|
|
67
|
+
// Appends one proxy entry to the queue at the current entryCount position, expanding the entries
|
|
68
|
+
// array if needed. The sort key is set by the caller; call sortRenderQueue afterward for order.
|
|
69
|
+
export function pushRenderQueueEntry(queue, proxy, sortKey) {
|
|
70
|
+
const entry = { proxy, sortKey };
|
|
71
|
+
if (queue.entryCount < queue.entries.length) {
|
|
72
|
+
queue.entries[queue.entryCount] = entry;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
queue.entries.push(entry);
|
|
76
|
+
}
|
|
77
|
+
queue.entryCount++;
|
|
78
|
+
}
|
|
79
|
+
// Sorts queue entries in-place using a comparator function. The default comparator sorts ascending
|
|
80
|
+
// by sort key, which preserves scene-graph order when keys are the encounter index from
|
|
81
|
+
// buildRenderQueue. Pass a custom comparator to implement opaque-front-to-back /
|
|
82
|
+
// transparent-back-to-front partitioning using packRenderSortKey.
|
|
83
|
+
export function sortRenderQueue(queue, compare) {
|
|
84
|
+
// Sort only the valid window [0..entryCount) of the entries array.
|
|
85
|
+
const slice = queue.entries.slice(0, queue.entryCount);
|
|
86
|
+
slice.sort(compare ?? compareRenderQueueEntriesByKey);
|
|
87
|
+
for (let i = 0; i < slice.length; i++) {
|
|
88
|
+
queue.entries[i] = slice[i];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function compareRenderQueueEntriesByKey(a, b) {
|
|
92
|
+
return a.sortKey - b.sortKey;
|
|
93
|
+
}
|
|
94
|
+
// Module-level scratch stack used by buildRenderQueue. Not shared with the per-state tempStack or
|
|
95
|
+
// the drawDriver's _drawStack, so prepare, draw, and queue-build can be interleaved safely.
|
|
96
|
+
const _buildStack = [];
|
|
97
|
+
//# sourceMappingURL=renderQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderQueue.js","sourceRoot":"","sources":["../src/renderQueue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAWhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,mGAAmG;AACnG,kGAAkG;AAClG,gGAAgG;AAChG,oGAAoG;AACpG,EAAE;AACF,+EAA+E;AAC/E,sDAAsD;AACtD,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,MAAkB,EAAE,GAAgB;IACvF,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtB,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAC9C,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,OAAO,WAAW,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,SAAS;QAC7B,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC5B,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QAC/C,CAAC;QACD,UAAU,EAAE,CAAC;QACb,gGAAgG;QAChG,uFAAuF;QACvF,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAkB,CAAC,CAAC,QAAQ,CAAC;QAC7D,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,wEAAwE;AACxE,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,yBAAyB,CAAC,CAAmB,EAAE,CAAmB;IAChF,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;AAC/B,CAAC;AAED,6FAA6F;AAC7F,qGAAqG;AACrG,MAAM,UAAU,iBAAiB;IAC/B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,4FAA4F;AAC5F,0FAA0F;AAC1F,iFAAiF;AACjF,EAAE;AACF,yDAAyD;AACzD,6CAA6C;AAC7C,oEAAoE;AACpE,+EAA+E;AAC/E,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,KAAa,EAAE,aAAsB;IACpF,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC3E,MAAM,cAAc,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IACnF,OAAO,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC;AAChD,CAAC;AAED,iGAAiG;AACjG,gGAAgG;AAChG,MAAM,UAAU,oBAAoB,CAAC,KAAkB,EAAE,KAAkB,EAAE,OAAsB;IACjG,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACjC,IAAI,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5C,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,KAAK,CAAC,UAAU,EAAE,CAAC;AACrB,CAAC;AAED,mGAAmG;AACnG,wFAAwF;AACxF,iFAAiF;AACjF,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAC7B,KAAkB,EAClB,OAA8D;IAE9D,mEAAmE;IACnE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,8BAA8B,CAAC,CAAC;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,SAAS,8BAA8B,CAAC,CAAmB,EAAE,CAAmB;IAC9E,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;AAC/B,CAAC;AAED,kGAAkG;AAClG,4FAA4F;AAC5F,MAAM,WAAW,GAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RenderState, RenderStateRuntime } from '@flighthq/types';
|
|
2
|
+
export declare function createRenderState(obj?: Partial<RenderState>): RenderState;
|
|
3
|
+
export declare function createRenderStateRuntime(): RenderStateRuntime;
|
|
4
|
+
export declare function getRenderStateRuntime(state: RenderState): RenderStateRuntime;
|
|
5
|
+
//# sourceMappingURL=renderState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderState.d.ts","sourceRoot":"","sources":["../src/renderState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGvE,wBAAgB,iBAAiB,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAiBzE;AAOD,wBAAgB,wBAAwB,IAAI,kBAAkB,CAU7D;AAID,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,CAE5E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createEntity, createEntityRuntime } from '@flighthq/entity';
|
|
2
|
+
import { BlendMode, EntityRuntimeKey } from '@flighthq/types';
|
|
3
|
+
export function createRenderState(obj) {
|
|
4
|
+
const state = createEntity({
|
|
5
|
+
allowSmoothing: obj?.allowSmoothing ?? true,
|
|
6
|
+
backgroundColor: obj?.backgroundColor ?? 0,
|
|
7
|
+
backgroundColorRgba: obj?.backgroundColorRgba ?? [],
|
|
8
|
+
backgroundColorString: obj?.backgroundColorString ?? '',
|
|
9
|
+
currentClipDepth: obj?.currentClipDepth ?? 0,
|
|
10
|
+
displayObjectClipHooks: obj?.displayObjectClipHooks ?? null,
|
|
11
|
+
pixelRatio: obj?.pixelRatio ?? 1,
|
|
12
|
+
renderAlpha: obj?.renderAlpha ?? 1,
|
|
13
|
+
renderBlendMode: obj?.renderBlendMode ?? BlendMode.Normal,
|
|
14
|
+
renderTransform2D: obj?.renderTransform2D ?? null,
|
|
15
|
+
roundPixels: obj?.roundPixels ?? false,
|
|
16
|
+
sceneGraphSyncPolicy: obj?.sceneGraphSyncPolicy ?? 'refreshDerivedState',
|
|
17
|
+
});
|
|
18
|
+
state[EntityRuntimeKey] = createRenderStateRuntime();
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
// Allocates the package-private machinery runtime for a RenderState: the frame counter, proxy maps,
|
|
22
|
+
// and renderer registry shared across every backend. createRenderState attaches one under
|
|
23
|
+
// EntityRuntimeKey; getRenderStateRuntime reads it back. Backend factories build their fuller runtime
|
|
24
|
+
// on top of this. The render path writes the returned object every frame, so the return is
|
|
25
|
+
// intentionally mutable (not Readonly).
|
|
26
|
+
export function createRenderStateRuntime() {
|
|
27
|
+
const runtime = createEntityRuntime();
|
|
28
|
+
runtime.currentFrameId = 0;
|
|
29
|
+
runtime.renderAdaptHook = null;
|
|
30
|
+
runtime.renderProxyAdapterMap = new WeakMap();
|
|
31
|
+
runtime.renderProxyMap = new WeakMap();
|
|
32
|
+
runtime.rendererMap = new Map();
|
|
33
|
+
runtime.rendererMapId = 0;
|
|
34
|
+
runtime.tempStack = [];
|
|
35
|
+
return runtime;
|
|
36
|
+
}
|
|
37
|
+
// Resolves the package-private machinery runtime attached to a RenderState. Mutable by design: the
|
|
38
|
+
// render path writes its fields every frame.
|
|
39
|
+
export function getRenderStateRuntime(state) {
|
|
40
|
+
return state[EntityRuntimeKey];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=renderState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderState.js","sourceRoot":"","sources":["../src/renderState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,UAAU,iBAAiB,CAAC,GAA0B;IAC1D,MAAM,KAAK,GAAG,YAAY,CAAC;QACzB,cAAc,EAAE,GAAG,EAAE,cAAc,IAAI,IAAI;QAC3C,eAAe,EAAE,GAAG,EAAE,eAAe,IAAI,CAAC;QAC1C,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,IAAI,EAAE;QACnD,qBAAqB,EAAE,GAAG,EAAE,qBAAqB,IAAI,EAAE;QACvD,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,IAAI,CAAC;QAC5C,sBAAsB,EAAE,GAAG,EAAE,sBAAsB,IAAI,IAAI;QAC3D,UAAU,EAAE,GAAG,EAAE,UAAU,IAAI,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,WAAW,IAAI,CAAC;QAClC,eAAe,EAAE,GAAG,EAAE,eAAe,IAAI,SAAS,CAAC,MAAM;QACzD,iBAAiB,EAAE,GAAG,EAAE,iBAAiB,IAAI,IAAI;QACjD,WAAW,EAAE,GAAG,EAAE,WAAW,IAAI,KAAK;QACtC,oBAAoB,EAAE,GAAG,EAAE,oBAAoB,IAAI,qBAAqB;KACzE,CAAgB,CAAC;IAClB,KAAK,CAAC,gBAAgB,CAAC,GAAG,wBAAwB,EAAE,CAAC;IACrD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oGAAoG;AACpG,0FAA0F;AAC1F,sGAAsG;AACtG,2FAA2F;AAC3F,wCAAwC;AACxC,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAG,mBAAmB,EAAwB,CAAC;IAC5D,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,qBAAqB,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9C,OAAO,CAAC,cAAc,GAAG,IAAI,OAAO,EAAE,CAAC;IACvC,OAAO,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mGAAmG;AACnG,6CAA6C;AAC7C,MAAM,UAAU,qBAAqB,CAAC,KAAkB;IACtD,OAAO,KAAK,CAAC,gBAAgB,CAAuB,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DisplayObject, MatrixLike, RectangleLike } from '@flighthq/types';
|
|
2
|
+
export type RenderTargetSizeOptions = {
|
|
3
|
+
minWidth?: number;
|
|
4
|
+
minHeight?: number;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Writes into outRenderTransform the transform to set as state.renderTransform2D when
|
|
8
|
+
* capturing source into a render target. Maps source content into target pixel space so
|
|
9
|
+
* that the bounds origin lands at (contentX, contentY).
|
|
10
|
+
*/
|
|
11
|
+
export declare function computeDisplayObjectRenderTargetTransform(outRenderTransform: MatrixLike, source: DisplayObject, bounds: Readonly<RectangleLike>, contentX?: number, contentY?: number): void;
|
|
12
|
+
/**
|
|
13
|
+
* Writes into outCacheTransform the transform to pass to the cache resolver so the
|
|
14
|
+
* cached image is placed back at the original scene position.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeRenderCacheTransform(outCacheTransform: MatrixLike, bounds: Readonly<RectangleLike>, contentX?: number, contentY?: number): void;
|
|
17
|
+
export declare function computeRenderTargetSize(bounds: Readonly<RectangleLike>, padding?: number, minWidth?: number, minHeight?: number): {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=renderTarget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTarget.d.ts","sourceRoot":"","sources":["../src/renderTarget.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhF,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,yCAAyC,CACvD,kBAAkB,EAAE,UAAU,EAC9B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,QAAQ,GAAE,MAAU,EACpB,QAAQ,GAAE,MAAU,GACnB,IAAI,CAUN;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,UAAU,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,QAAQ,GAAE,MAAU,EACpB,QAAQ,GAAE,MAAU,GACnB,IAAI,CAON;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,OAAO,GAAE,MAAU,EACnB,QAAQ,GAAE,MAAU,EACpB,SAAS,GAAE,MAAU,GACpB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKnC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createMatrix, inverseMatrix, multiplyMatrix } from '@flighthq/geometry';
|
|
2
|
+
import { getNodeLocalTransformMatrix } from '@flighthq/node';
|
|
3
|
+
/**
|
|
4
|
+
* Writes into outRenderTransform the transform to set as state.renderTransform2D when
|
|
5
|
+
* capturing source into a render target. Maps source content into target pixel space so
|
|
6
|
+
* that the bounds origin lands at (contentX, contentY).
|
|
7
|
+
*/
|
|
8
|
+
export function computeDisplayObjectRenderTargetTransform(outRenderTransform, source, bounds, contentX = 0, contentY = 0) {
|
|
9
|
+
const localTransform = getNodeLocalTransformMatrix(source);
|
|
10
|
+
inverseMatrix(_tempInvLocal, localTransform);
|
|
11
|
+
_tempTranslation.a = 1;
|
|
12
|
+
_tempTranslation.b = 0;
|
|
13
|
+
_tempTranslation.c = 0;
|
|
14
|
+
_tempTranslation.d = 1;
|
|
15
|
+
_tempTranslation.tx = contentX - bounds.x;
|
|
16
|
+
_tempTranslation.ty = contentY - bounds.y;
|
|
17
|
+
multiplyMatrix(outRenderTransform, _tempTranslation, _tempInvLocal);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Writes into outCacheTransform the transform to pass to the cache resolver so the
|
|
21
|
+
* cached image is placed back at the original scene position.
|
|
22
|
+
*/
|
|
23
|
+
export function computeRenderCacheTransform(outCacheTransform, bounds, contentX = 0, contentY = 0) {
|
|
24
|
+
outCacheTransform.a = 1;
|
|
25
|
+
outCacheTransform.b = 0;
|
|
26
|
+
outCacheTransform.c = 0;
|
|
27
|
+
outCacheTransform.d = 1;
|
|
28
|
+
outCacheTransform.tx = bounds.x - contentX;
|
|
29
|
+
outCacheTransform.ty = bounds.y - contentY;
|
|
30
|
+
}
|
|
31
|
+
export function computeRenderTargetSize(bounds, padding = 0, minWidth = 1, minHeight = 1) {
|
|
32
|
+
return {
|
|
33
|
+
width: Math.max(minWidth, Math.ceil(bounds.width) + padding * 2),
|
|
34
|
+
height: Math.max(minHeight, Math.ceil(bounds.height) + padding * 2),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const _tempInvLocal = createMatrix();
|
|
38
|
+
const _tempTranslation = createMatrix();
|
|
39
|
+
//# sourceMappingURL=renderTarget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTarget.js","sourceRoot":"","sources":["../src/renderTarget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAQ7D;;;;GAIG;AACH,MAAM,UAAU,yCAAyC,CACvD,kBAA8B,EAC9B,MAAqB,EACrB,MAA+B,EAC/B,WAAmB,CAAC,EACpB,WAAmB,CAAC;IAEpB,MAAM,cAAc,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC3D,aAAa,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC7C,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC;IACvB,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC;IACvB,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC;IACvB,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC;IACvB,gBAAgB,CAAC,EAAE,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC;IAC1C,cAAc,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC;AACtE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,iBAA6B,EAC7B,MAA+B,EAC/B,WAAmB,CAAC,EACpB,WAAmB,CAAC;IAEpB,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,iBAAiB,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC3C,iBAAiB,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,MAA+B,EAC/B,UAAkB,CAAC,EACnB,WAAmB,CAAC,EACpB,YAAoB,CAAC;IAErB,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;QAChE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,YAAY,EAAE,CAAC;AACrC,MAAM,gBAAgB,GAAG,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTransform2d.d.ts","sourceRoot":"","sources":["../src/renderTransform2d.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAwB,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAIxF,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,aAAa,EACnB,UAAU,CAAC,EAAE,aAAa,GACzB,OAAO,CAYT"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { copyMatrix, multiplyMatrix } from '@flighthq/geometry';
|
|
2
|
+
import { getNodeLocalTransformMatrix, getNodeLocalTransformRevision } from '@flighthq/node';
|
|
3
|
+
import { getRenderStateRuntime } from './renderState';
|
|
4
|
+
export function updateRenderProxy2DTransform(state, data, parentData) {
|
|
5
|
+
const localTransformId = getNodeLocalTransformRevision(data.source);
|
|
6
|
+
const parentDirty = parentData !== undefined && parentData.transformFrameId === getRenderStateRuntime(state).currentFrameId;
|
|
7
|
+
const localDirty = data.lastLocalTransformId !== localTransformId;
|
|
8
|
+
if (parentDirty || localDirty) {
|
|
9
|
+
recalculateRenderTransform2D(state, data, parentData);
|
|
10
|
+
data.lastLocalTransformId = localTransformId;
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
function recalculateRenderTransform2D(state, data, parentData) {
|
|
16
|
+
const transform2D = getNodeLocalTransformMatrix(data.source);
|
|
17
|
+
const parentTransform2D = parentData !== undefined ? parentData.transform2D : state.renderTransform2D;
|
|
18
|
+
if (parentTransform2D !== null) {
|
|
19
|
+
multiplyMatrix(data.transform2D, parentTransform2D, transform2D);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
copyMatrix(data.transform2D, transform2D);
|
|
23
|
+
}
|
|
24
|
+
data.transformFrameId = getRenderStateRuntime(state).currentFrameId;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=renderTransform2d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTransform2d.js","sourceRoot":"","sources":["../src/renderTransform2d.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAG5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,UAAU,4BAA4B,CAC1C,KAAkB,EAClB,IAAmB,EACnB,UAA0B;IAE1B,MAAM,gBAAgB,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAc,CAAC,CAAC;IAC5E,MAAM,WAAW,GACf,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,gBAAgB,KAAK,qBAAqB,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC;IAC1G,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,KAAK,gBAAgB,CAAC;IAElE,IAAI,WAAW,IAAI,UAAU,EAAE,CAAC;QAC9B,4BAA4B,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,oBAAoB,GAAG,gBAAgB,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAkB,EAAE,IAAmB,EAAE,UAA0B;IACvG,MAAM,WAAW,GAAG,2BAA2B,CAAC,IAAI,CAAC,MAA+B,CAAC,CAAC;IACtF,MAAM,iBAAiB,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;IACtG,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC;IACnE,CAAC;SAAM,CAAC;QACN,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC,gBAAgB,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Matrix, Rectangle, RenderProxy2D, RenderViewport2D } from '@flighthq/types';
|
|
2
|
+
export declare function computeRenderProxyWorldBounds(out: Pick<Rectangle, 'x' | 'y' | 'width' | 'height'>, source: unknown): boolean;
|
|
3
|
+
export declare function createRenderViewport2D(x: number, y: number, width: number, height: number): RenderViewport2D;
|
|
4
|
+
export declare function isRenderableInViewport(source: unknown, viewport: Readonly<RenderViewport2D>, renderTransform2D?: Readonly<Matrix> | null): boolean;
|
|
5
|
+
export declare function isRenderProxyInViewport(proxy: Readonly<RenderProxy2D>, viewport: Readonly<RenderViewport2D>, renderTransform2D?: Readonly<Matrix> | null): boolean;
|
|
6
|
+
//# sourceMappingURL=renderViewport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderViewport.d.ts","sourceRoot":"","sources":["../src/renderViewport.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAiB,MAAM,iBAAiB,CAAC;AAKzG,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,CAAC,EACpD,MAAM,EAAE,OAAO,GACd,OAAO,CAQT;AAGD,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAE5G;AAOD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACpC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,GAC1C,OAAO,CAoBT;AAID,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EACpC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,GAC1C,OAAO,CAET"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createRectangle, matrixTransformRectangle } from '@flighthq/geometry';
|
|
2
|
+
import { getNodeWorldBoundsRectangle } from '@flighthq/node';
|
|
3
|
+
// Writes the world-space axis-aligned bounding box of `source` into `out`. Returns true when
|
|
4
|
+
// `source` is a Spatial2DNode and the bounds were written; returns false and leaves `out`
|
|
5
|
+
// unchanged when the source has no spatial traits.
|
|
6
|
+
export function computeRenderProxyWorldBounds(out, source) {
|
|
7
|
+
if (!isSpatial2DNode(source))
|
|
8
|
+
return false;
|
|
9
|
+
const worldBounds = getNodeWorldBoundsRectangle(source);
|
|
10
|
+
out.x = worldBounds.x;
|
|
11
|
+
out.y = worldBounds.y;
|
|
12
|
+
out.width = worldBounds.width;
|
|
13
|
+
out.height = worldBounds.height;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
// Allocates and returns a new RenderViewport2D with the given screen-space region.
|
|
17
|
+
export function createRenderViewport2D(x, y, width, height) {
|
|
18
|
+
return { height, width, x, y };
|
|
19
|
+
}
|
|
20
|
+
// Returns true when `source` may be visible within `viewport`. Conservative: returns true when
|
|
21
|
+
// the source carries no spatial traits (bounds unknown). When spatial bounds are available, uses
|
|
22
|
+
// an inclusive overlap test on all four edges so that a zero-size object touching any viewport
|
|
23
|
+
// edge is considered in-viewport. When `renderTransform2D` is provided, the world bounds are
|
|
24
|
+
// transformed into screen space before the overlap test.
|
|
25
|
+
export function isRenderableInViewport(source, viewport, renderTransform2D) {
|
|
26
|
+
if (!computeRenderProxyWorldBounds(_scratchBounds, source))
|
|
27
|
+
return true;
|
|
28
|
+
let bounds = _scratchBounds;
|
|
29
|
+
if (renderTransform2D != null) {
|
|
30
|
+
matrixTransformRectangle(_scratchTransformed, renderTransform2D, _scratchBounds);
|
|
31
|
+
bounds = _scratchTransformed;
|
|
32
|
+
}
|
|
33
|
+
const objMinX = bounds.x;
|
|
34
|
+
const objMinY = bounds.y;
|
|
35
|
+
const objMaxX = bounds.x + bounds.width;
|
|
36
|
+
const objMaxY = bounds.y + bounds.height;
|
|
37
|
+
const vpMinX = viewport.x;
|
|
38
|
+
const vpMinY = viewport.y;
|
|
39
|
+
const vpMaxX = viewport.x + viewport.width;
|
|
40
|
+
const vpMaxY = viewport.y + viewport.height;
|
|
41
|
+
return !(objMaxX < vpMinX || objMinX > vpMaxX || objMaxY < vpMinY || objMinY > vpMaxY);
|
|
42
|
+
}
|
|
43
|
+
// Returns true when the render proxy's source may be visible within `viewport`. Delegates to
|
|
44
|
+
// isRenderableInViewport using the proxy's source.
|
|
45
|
+
export function isRenderProxyInViewport(proxy, viewport, renderTransform2D) {
|
|
46
|
+
return isRenderableInViewport(proxy.source, viewport, renderTransform2D);
|
|
47
|
+
}
|
|
48
|
+
// Detects whether `source` carries the HasTransform2D trait (and thus is at least a Transform2DNode).
|
|
49
|
+
// Nodes that pass through createRenderProxy2D carry both HasTransform2D and HasBoundsRectangle,
|
|
50
|
+
// making them Spatial2DNode — the bounds runtime is guaranteed present.
|
|
51
|
+
function isSpatial2DNode(source) {
|
|
52
|
+
return source !== null && typeof source === 'object' && 'pivotX' in source;
|
|
53
|
+
}
|
|
54
|
+
// Module-level scratch rectangles used by isRenderableInViewport to avoid allocation on every call.
|
|
55
|
+
const _scratchBounds = createRectangle();
|
|
56
|
+
const _scratchTransformed = createRectangle();
|
|
57
|
+
//# sourceMappingURL=renderViewport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderViewport.js","sourceRoot":"","sources":["../src/renderViewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAG7D,6FAA6F;AAC7F,0FAA0F;AAC1F,mDAAmD;AACnD,MAAM,UAAU,6BAA6B,CAC3C,GAAoD,EACpD,MAAe;IAEf,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,WAAW,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACxD,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IACtB,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IACtB,GAAG,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;IAC9B,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;IAChC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,sBAAsB,CAAC,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc;IACxF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACjC,CAAC;AAED,+FAA+F;AAC/F,iGAAiG;AACjG,+FAA+F;AAC/F,6FAA6F;AAC7F,yDAAyD;AACzD,MAAM,UAAU,sBAAsB,CACpC,MAAe,EACf,QAAoC,EACpC,iBAA2C;IAE3C,IAAI,CAAC,6BAA6B,CAAC,cAAc,EAAE,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAExE,IAAI,MAAM,GAAG,cAAc,CAAC;IAC5B,IAAI,iBAAiB,IAAI,IAAI,EAAE,CAAC;QAC9B,wBAAwB,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC;QACjF,MAAM,GAAG,mBAAmB,CAAC;IAC/B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IAEzC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;IAE5C,OAAO,CAAC,CAAC,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,MAAM,CAAC,CAAC;AACzF,CAAC;AAED,6FAA6F;AAC7F,mDAAmD;AACnD,MAAM,UAAU,uBAAuB,CACrC,KAA8B,EAC9B,QAAoC,EACpC,iBAA2C;IAE3C,OAAO,sBAAsB,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC3E,CAAC;AAED,sGAAsG;AACtG,gGAAgG;AAChG,wEAAwE;AACxE,SAAS,eAAe,CAAC,MAAe;IACtC,OAAO,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,QAAQ,IAAK,MAAiB,CAAC;AACzF,CAAC;AAED,oGAAoG;AACpG,MAAM,cAAc,GAAG,eAAe,EAAE,CAAC;AACzC,MAAM,mBAAmB,GAAG,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Kind, Renderable, Renderer, RendererData, RenderState } from '@flighthq/types';
|
|
2
|
+
export declare function copyAllRenderersFromRenderState(target: RenderState, source: RenderState): void;
|
|
3
|
+
export declare function copyRenderersFromRenderState(target: RenderState, source: RenderState): void;
|
|
4
|
+
export declare function noopRendererData(_state: RenderState, _source: Renderable): RendererData | null;
|
|
5
|
+
export declare function registerRenderer(state: RenderState, kind: Kind, renderer: Renderer): void;
|
|
6
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAM7F,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAG9F;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAI3F;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAE9F;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAKzF"}
|
package/dist/renderer.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getRenderStateRuntime } from './renderState';
|
|
2
|
+
// Mask renderers were retired (a mask is now a path ClipRegion realized by the backend clip hooks), so
|
|
3
|
+
// there is no mask-renderer registry to copy — only the kind→renderer map and the clip hooks.
|
|
4
|
+
export function copyAllRenderersFromRenderState(target, source) {
|
|
5
|
+
copyRenderersFromRenderState(target, source);
|
|
6
|
+
if (source.displayObjectClipHooks !== null)
|
|
7
|
+
target.displayObjectClipHooks = source.displayObjectClipHooks;
|
|
8
|
+
}
|
|
9
|
+
export function copyRenderersFromRenderState(target, source) {
|
|
10
|
+
getRenderStateRuntime(source).rendererMap.forEach((renderer, kind) => {
|
|
11
|
+
registerRenderer(target, kind, renderer);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function noopRendererData(_state, _source) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
export function registerRenderer(state, kind, renderer) {
|
|
18
|
+
const runtime = getRenderStateRuntime(state);
|
|
19
|
+
if (runtime.rendererMap.get(kind) === renderer)
|
|
20
|
+
return;
|
|
21
|
+
runtime.rendererMapId = (runtime.rendererMapId + 1) >>> 0;
|
|
22
|
+
runtime.rendererMap.set(kind, renderer);
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,uGAAuG;AACvG,8FAA8F;AAC9F,MAAM,UAAU,+BAA+B,CAAC,MAAmB,EAAE,MAAmB;IACtF,4BAA4B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,sBAAsB,KAAK,IAAI;QAAE,MAAM,CAAC,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,CAAC;AAC5G,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAmB,EAAE,MAAmB;IACnF,qBAAqB,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE;QACnE,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAmB,EAAE,OAAmB;IACvE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,IAAU,EAAE,QAAkB;IACjF,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO;IACvD,OAAO,CAAC,aAAa,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAC1D,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Camera, RenderState, SceneLightBlock, SceneLights, SceneNode, SceneRenderList } from '@flighthq/types';
|
|
2
|
+
export declare function packSceneLightBlock(out: SceneLightBlock, lights: Readonly<SceneLights>): void;
|
|
3
|
+
export declare function prepareSceneRender(state: RenderState, scene: Readonly<SceneNode>, camera: Readonly<Camera>, lights: Readonly<SceneLights>): SceneRenderList;
|
|
4
|
+
//# sourceMappingURL=sceneRender.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneRender.d.ts","sourceRoot":"","sources":["../src/sceneRender.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAGV,MAAM,EAMN,WAAW,EACX,eAAe,EACf,WAAW,EACX,SAAS,EACT,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAazB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CA6B7F;AAcD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,EAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EACxB,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,eAAe,CAiBjB"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createAabb, createFrustum, createMatrix4, isFrustumIntersectingAabb, multiplyMatrix4, setFrustumFromMatrix4, setOrthographicMatrix4, setPerspectiveMatrix4, transformAabbByMatrix4, } from '@flighthq/geometry';
|
|
2
|
+
import { unpackColorToLinear } from '@flighthq/materials';
|
|
3
|
+
import { getNodeRuntime, getNodeWorldTransformMatrix4 } from '@flighthq/node';
|
|
4
|
+
// Packs the directional + ambient draw-arg lights into `out` (the GPU-ready light block), converting
|
|
5
|
+
// each packed sRgb color to linear, premultiplied radiance (unpackColorToLinear(color) * intensity)
|
|
6
|
+
// so the shader never sees sRgb. Sets the presence counts (0 or 1 each). The float layout matches the
|
|
7
|
+
// shader's std140 light block: directional { direction.xyz, _pad, radiance.rgb, _pad } then ambient
|
|
8
|
+
// { radiance.rgb, _pad }. An absent term leaves its slots zeroed.
|
|
9
|
+
//
|
|
10
|
+
// `version` bumps only when the packed data or counts actually change from the previous pack — a
|
|
11
|
+
// no-op re-pack of identical lights leaves it untouched. This is the SceneLightBlock contract a
|
|
12
|
+
// backend keyed off `version` relies on to skip re-uploading an unchanged block across frames; a
|
|
13
|
+
// blind per-frame bump would defeat that skip. Packs into a scratch, compares, then commits only on
|
|
14
|
+
// change so an unchanged block is never dirtied.
|
|
15
|
+
export function packSceneLightBlock(out, lights) {
|
|
16
|
+
scratchLightData.fill(0);
|
|
17
|
+
let directionalCount = 0;
|
|
18
|
+
const directional = lights.directional;
|
|
19
|
+
if (directional !== null) {
|
|
20
|
+
packDirectionalLight(scratchLightData, directional);
|
|
21
|
+
directionalCount = 1;
|
|
22
|
+
}
|
|
23
|
+
let ambientCount = 0;
|
|
24
|
+
const ambient = lights.ambient;
|
|
25
|
+
if (ambient !== null) {
|
|
26
|
+
packAmbientLight(scratchLightData, ambient);
|
|
27
|
+
ambientCount = 1;
|
|
28
|
+
}
|
|
29
|
+
if (out.directionalCount === directionalCount &&
|
|
30
|
+
out.ambientCount === ambientCount &&
|
|
31
|
+
isFloat32ArrayEqual(out.data, scratchLightData)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
out.data.set(scratchLightData);
|
|
35
|
+
out.directionalCount = directionalCount;
|
|
36
|
+
out.ambientCount = ambientCount;
|
|
37
|
+
out.version++;
|
|
38
|
+
}
|
|
39
|
+
// The per-frame preparation pass for a 3D scene, the 3D analog of prepareDisplayObjectRender. It is
|
|
40
|
+
// backend-agnostic (no GPU context): it walks the SceneNode hierarchy rooted at `scene`, propagating
|
|
41
|
+
// each node's worldMatrix (parentWorld x localMatrix, resolved lazily on the node runtime and
|
|
42
|
+
// alias-safe), computes the draw camera's view-projection, frustum-culls every Mesh against its
|
|
43
|
+
// world-space bounds, and packs `lights` into the shared SceneLightBlock (sRgb->linear at pack time).
|
|
44
|
+
// The returned SceneRenderList is the render-ready frame the backend drawScene consumes — it only
|
|
45
|
+
// has to upload buffers, bind, and draw the visible meshes.
|
|
46
|
+
//
|
|
47
|
+
// `aspect` for a perspective camera is taken from the render state's pixel-space target (width /
|
|
48
|
+
// height); a degenerate target falls back to 1. The returned list is reused scratch owned per render
|
|
49
|
+
// state (so a gl state and a wgpu state prepare independently); a caller must not retain it past the
|
|
50
|
+
// drawScene it feeds.
|
|
51
|
+
export function prepareSceneRender(state, scene, camera, lights) {
|
|
52
|
+
const prepared = ensurePreparedScene(state);
|
|
53
|
+
const list = prepared.list;
|
|
54
|
+
// RenderState carries no canonical viewport size, so a perspective camera supplies its own aspect
|
|
55
|
+
// through its projection; this neutral fallback keeps an orthographic frame and a pre-aspected
|
|
56
|
+
// perspective frame correct. A backend that owns a sized target sets the projection aspect first.
|
|
57
|
+
setSceneViewProjectionMatrix4(prepared.viewProjection, camera, DEFAULT_VIEWPORT_ASPECT);
|
|
58
|
+
setFrustumFromMatrix4(prepared.frustum, prepared.viewProjection);
|
|
59
|
+
packSceneLightBlock(list.lights, lights);
|
|
60
|
+
prepared.meshes.length = 0;
|
|
61
|
+
collectVisibleMeshes(scene, prepared.frustum, prepared.worldBounds, prepared.meshes);
|
|
62
|
+
list.meshCount = prepared.meshes.length;
|
|
63
|
+
return list;
|
|
64
|
+
}
|
|
65
|
+
function collectVisibleMeshes(node, frustum, worldBounds, out) {
|
|
66
|
+
if (!node.enabled) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// A node is a drawable Mesh (not a transform-only group) when it carries geometry. Structural,
|
|
70
|
+
// so it holds for Meshes created with a custom kind, not just MeshKind.
|
|
71
|
+
const mesh = node;
|
|
72
|
+
if (mesh.geometry != null && isMeshVisible(mesh, frustum, worldBounds)) {
|
|
73
|
+
out.push(mesh);
|
|
74
|
+
}
|
|
75
|
+
const children = getNodeRuntime(node).children;
|
|
76
|
+
if (children !== null) {
|
|
77
|
+
for (let i = 0; i < children.length; i++) {
|
|
78
|
+
collectVisibleMeshes(children[i], frustum, worldBounds, out);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function ensurePreparedScene(state) {
|
|
83
|
+
let prepared = preparedScenes.get(state);
|
|
84
|
+
if (prepared === undefined) {
|
|
85
|
+
const viewProjection = createMatrix4();
|
|
86
|
+
const meshes = [];
|
|
87
|
+
const list = {
|
|
88
|
+
lights: {
|
|
89
|
+
ambientCount: 0,
|
|
90
|
+
data: new Float32Array(LIGHT_BLOCK_FLOATS),
|
|
91
|
+
directionalCount: 0,
|
|
92
|
+
hemisphereCount: 0,
|
|
93
|
+
pointCount: 0,
|
|
94
|
+
spotCount: 0,
|
|
95
|
+
version: 0,
|
|
96
|
+
},
|
|
97
|
+
meshCount: 0,
|
|
98
|
+
viewProjection: viewProjection,
|
|
99
|
+
visibleMeshes: meshes,
|
|
100
|
+
};
|
|
101
|
+
prepared = {
|
|
102
|
+
frustum: createFrustum(),
|
|
103
|
+
list: list,
|
|
104
|
+
meshes: meshes,
|
|
105
|
+
viewProjection: viewProjection,
|
|
106
|
+
worldBounds: createAabb(),
|
|
107
|
+
};
|
|
108
|
+
preparedScenes.set(state, prepared);
|
|
109
|
+
}
|
|
110
|
+
return prepared;
|
|
111
|
+
}
|
|
112
|
+
function isFloat32ArrayEqual(a, b) {
|
|
113
|
+
if (a.length !== b.length)
|
|
114
|
+
return false;
|
|
115
|
+
for (let i = 0; i < a.length; i++) {
|
|
116
|
+
if (a[i] !== b[i])
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
function isMeshVisible(mesh, frustum, worldBounds) {
|
|
122
|
+
const bounds = mesh.geometry.bounds;
|
|
123
|
+
if (bounds === null) {
|
|
124
|
+
// No cached local bounds: cannot cull, so conservatively keep the mesh.
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
transformAabbByMatrix4(worldBounds, bounds, getNodeWorldTransformMatrix4(mesh));
|
|
128
|
+
return isFrustumIntersectingAabb(frustum, worldBounds);
|
|
129
|
+
}
|
|
130
|
+
function packAmbientLight(data, ambient) {
|
|
131
|
+
unpackColorToLinear(scratchColor, ambient.color);
|
|
132
|
+
const intensity = ambient.intensity;
|
|
133
|
+
data[8] = scratchColor[0] * intensity;
|
|
134
|
+
data[9] = scratchColor[1] * intensity;
|
|
135
|
+
data[10] = scratchColor[2] * intensity;
|
|
136
|
+
}
|
|
137
|
+
function packDirectionalLight(data, directional) {
|
|
138
|
+
data[0] = directional.direction.x;
|
|
139
|
+
data[1] = directional.direction.y;
|
|
140
|
+
data[2] = directional.direction.z;
|
|
141
|
+
unpackColorToLinear(scratchColor, directional.color);
|
|
142
|
+
const intensity = directional.intensity;
|
|
143
|
+
data[4] = scratchColor[0] * intensity;
|
|
144
|
+
data[5] = scratchColor[1] * intensity;
|
|
145
|
+
data[6] = scratchColor[2] * intensity;
|
|
146
|
+
}
|
|
147
|
+
// Composes the camera's view-projection (projection x view) into `out`. For a perspective camera the
|
|
148
|
+
// projection's own aspect is used when set (non-zero), else the render state's `aspect` fallback;
|
|
149
|
+
// near/far come from the camera. Reads camera fields through a scratch projection before the multiply,
|
|
150
|
+
// so it is safe even if `out` aliases the camera's view.
|
|
151
|
+
function setSceneViewProjectionMatrix4(out, camera, aspect) {
|
|
152
|
+
const projection = camera.projection;
|
|
153
|
+
if (projection.kind === 'perspective') {
|
|
154
|
+
// Geometry's setPerspectiveMatrix4 takes the tangent of the half-FOV, not the full angle.
|
|
155
|
+
setPerspectiveMatrix4(scratchProjection, Math.tan(projection.fovY * 0.5), projection.aspect !== 0 ? projection.aspect : aspect, camera.near, camera.far);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
setOrthographicMatrix4(scratchProjection, -projection.halfWidth, projection.halfWidth, -projection.halfHeight, projection.halfHeight, camera.near, camera.far);
|
|
159
|
+
}
|
|
160
|
+
multiplyMatrix4(out, scratchProjection, camera.view);
|
|
161
|
+
}
|
|
162
|
+
// Neutral viewport aspect used when a perspective camera does not carry its own.
|
|
163
|
+
const DEFAULT_VIEWPORT_ASPECT = 1;
|
|
164
|
+
// One directional ({ direction.xyz, _pad, radiance.rgb, _pad }) + one ambient ({ radiance.rgb,
|
|
165
|
+
// _pad }) = 12 floats, std140-aligned (vec4 boundaries).
|
|
166
|
+
const LIGHT_BLOCK_FLOATS = 12;
|
|
167
|
+
// Per-render-state prepared frames. Keyed by state so independent backends prepare without sharing
|
|
168
|
+
// scratch; a state's entry is freed when the state is GC'd.
|
|
169
|
+
const preparedScenes = new WeakMap();
|
|
170
|
+
const scratchColor = [0, 0, 0, 0];
|
|
171
|
+
const scratchProjection = createMatrix4();
|
|
172
|
+
// Reused staging buffer for packSceneLightBlock's pack-then-compare: the new block is packed here and
|
|
173
|
+
// committed to `out.data` only when it differs, so an unchanged block never bumps `version`.
|
|
174
|
+
const scratchLightData = new Float32Array(LIGHT_BLOCK_FLOATS);
|
|
175
|
+
//# sourceMappingURL=sceneRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneRender.js","sourceRoot":"","sources":["../src/sceneRender.ts"],"names":[],"mappings":"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"}
|