@absolutejs/rendering 0.1.0 → 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/README.md +52 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/renderTargetScope.d.ts +18 -0
- package/dist/renderTargetScope.js +47 -0
- package/dist/spring.d.ts +10 -0
- package/dist/spring.js +13 -0
- package/package.json +41 -4
package/README.md
CHANGED
|
@@ -35,3 +35,55 @@ This retains onBeforeCompile, customProgramCacheKey and onBeforeRender. A regist
|
|
|
35
35
|
Qualified against Three r186. No React dependency and no animation loop. Runtime cost is a small callback and destination check per affected draw; switching sampling modes can select another cached shader program. Hardware frame-rate improvements are not claimed. Game-specific foliage algorithms, lighting, world generation and simulation remain outside this package.
|
|
36
36
|
|
|
37
37
|
Use `bun run check:package` to build declarations and run the ownership/policy tests. Browser evidence is retained under docs/.
|
|
38
|
+
|
|
39
|
+
## Scoped captures and readback
|
|
40
|
+
|
|
41
|
+
`renderTargetScope(renderer, run)` restores the render target, cube face, mip,
|
|
42
|
+
viewport, scissor and scissor-test state even if synchronous work throws. The
|
|
43
|
+
callback must finish renderer mutations synchronously; do not hold a scope over
|
|
44
|
+
an await.
|
|
45
|
+
|
|
46
|
+
`readTargetPixelsScoped(renderer, target, width, height, buffer, textureIndex?)`
|
|
47
|
+
submits a byte/float read from a neutral target and restores the caller through
|
|
48
|
+
Three's target setter. This avoids restoring a resolve framebuffer in place of
|
|
49
|
+
its multisample draw attachment, or treating a cube framebuffer array as a single
|
|
50
|
+
framebuffer.
|
|
51
|
+
|
|
52
|
+
`readFloatTargetScoped(...)` submits asynchronous float readback in the same
|
|
53
|
+
neutral state, restores the caller immediately, and returns the exact supplied
|
|
54
|
+
Float32Array on completion. It never restores stale renderer state after await.
|
|
55
|
+
Allocate supported targets and correctly sized buffers before calling these
|
|
56
|
+
helpers. The helpers do not choose formats, sample counts or capture resolution.
|
|
57
|
+
|
|
58
|
+
## React Spring with demand-rendered Fiber scenes
|
|
59
|
+
|
|
60
|
+
The optional `@absolutejs/rendering/spring` entry provides `animated.mesh`,
|
|
61
|
+
`animated.group`, `useSpring`, `easings`, and `createFiberSpringHost` for other
|
|
62
|
+
explicit Fiber primitives:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { animated, useSpring } from '@absolutejs/rendering/spring';
|
|
66
|
+
|
|
67
|
+
function MovingGroup({ x }: { x: number }) {
|
|
68
|
+
const motion = useSpring({ x });
|
|
69
|
+
return <animated.group position-x={motion.x}>{/* scene content */}</animated.group>;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
It keeps React Spring's normal scheduler. Three prop updates invalidate the
|
|
74
|
+
owning Fiber root through `applyProps`; DOM-only animation does not render a
|
|
75
|
+
scene and can finish without a mounted Canvas. No `useFrame`, manual animation
|
|
76
|
+
clock, global scheduler replacement, or unconditional render loop is installed.
|
|
77
|
+
|
|
78
|
+
Do not also runtime-import `@react-spring/three`: that entry installs a global
|
|
79
|
+
Fiber-driven scheduler even when its consuming component is never mounted. This
|
|
80
|
+
adapter does not override or repair another module's global scheduler changes.
|
|
81
|
+
Type-only imports from that package are safe. Test your actual application's
|
|
82
|
+
eager import graph as well as isolated components.
|
|
83
|
+
|
|
84
|
+
Use `createFiberSpringHost(['instancedMesh', 'meshStandardMaterial'])` to opt into
|
|
85
|
+
additional hosts without registering every Three constructor. React, Fiber and
|
|
86
|
+
React Spring peers are optional for the core material utilities, but required
|
|
87
|
+
when using this subpath. `@react-spring/three` supplies host types only; it is not
|
|
88
|
+
runtime-imported by this entry. The tested versions are React 19.3, Fiber 9.8.2,
|
|
89
|
+
Three 0.186.1 and React Spring 10.1.2.
|
package/dist/index.d.ts
CHANGED
|
@@ -11,3 +11,4 @@ export declare function bindAlphaToCoverageDestination(material: Material, enabl
|
|
|
11
11
|
* Destination policy is cloned independently so changing one owner's preference
|
|
12
12
|
* cannot alter another. No source material is mutated. */
|
|
13
13
|
export declare function cloneRenderMaterial<T extends Material>(source: T): T;
|
|
14
|
+
export { renderTargetScope, readTargetPixelsScoped, readFloatTargetScoped, } from "./renderTargetScope.js";
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type WebGLRenderer } from "three";
|
|
2
|
+
/** Synchronous offscreen work; preserve target attachment, viewport and clipping.
|
|
3
|
+
* The callback must finish its renderer mutations before returning.
|
|
4
|
+
*/
|
|
5
|
+
export declare function renderTargetScope<T>(renderer: WebGLRenderer, run: () => T): T;
|
|
6
|
+
/** Start an async float diagnostic with a neutral current target, then immediately
|
|
7
|
+
* restore the caller's attachment. Three's async reader restores a raw framebuffer
|
|
8
|
+
* property before awaiting; cube/mipmap targets store arrays in that property.
|
|
9
|
+
* Keeping the neutral target only for submission avoids that invalid bind without
|
|
10
|
+
* holding renderer state across the asynchronous wait.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readFloatTargetScoped(renderer: WebGLRenderer, target: import("three").WebGLRenderTarget, width: number, height: number, buffer: Float32Array, textureIndex?: number): Promise<Float32Array>;
|
|
13
|
+
/** Synchronous authoring/diagnostic read. Three restores the raw resolve
|
|
14
|
+
* framebuffer, not a current target's multisample attachment, after reading.
|
|
15
|
+
* Submit from a neutral target and let setRenderTarget restore the actual
|
|
16
|
+
* attachment; otherwise the next draw can resolve stale samples over new data.
|
|
17
|
+
* This also avoids restoring cube/mip framebuffer arrays as a framebuffer. */
|
|
18
|
+
export declare function readTargetPixelsScoped(renderer: WebGLRenderer, target: import("three").WebGLRenderTarget, width: number, height: number, buffer: Uint8Array | Float32Array, textureIndex?: number): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Vector4 } from "three";
|
|
2
|
+
/** Synchronous offscreen work; preserve target attachment, viewport and clipping.
|
|
3
|
+
* The callback must finish its renderer mutations before returning.
|
|
4
|
+
*/
|
|
5
|
+
export function renderTargetScope(renderer, run) {
|
|
6
|
+
const target = renderer.getRenderTarget(), face = renderer.getActiveCubeFace(), mip = renderer.getActiveMipmapLevel();
|
|
7
|
+
const viewport = renderer.getViewport(new Vector4()), scissor = renderer.getScissor(new Vector4()), test = renderer.getScissorTest();
|
|
8
|
+
try {
|
|
9
|
+
renderer.setScissorTest(false);
|
|
10
|
+
return run();
|
|
11
|
+
}
|
|
12
|
+
finally {
|
|
13
|
+
renderer.setRenderTarget(target, face, mip);
|
|
14
|
+
renderer.setViewport(viewport);
|
|
15
|
+
renderer.setScissor(scissor);
|
|
16
|
+
renderer.setScissorTest(test);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Start an async float diagnostic with a neutral current target, then immediately
|
|
20
|
+
* restore the caller's attachment. Three's async reader restores a raw framebuffer
|
|
21
|
+
* property before awaiting; cube/mipmap targets store arrays in that property.
|
|
22
|
+
* Keeping the neutral target only for submission avoids that invalid bind without
|
|
23
|
+
* holding renderer state across the asynchronous wait.
|
|
24
|
+
*/
|
|
25
|
+
export function readFloatTargetScoped(renderer, target, width, height, buffer, textureIndex = 0) {
|
|
26
|
+
let pending;
|
|
27
|
+
renderTargetScope(renderer, () => {
|
|
28
|
+
renderer.setRenderTarget(null);
|
|
29
|
+
pending = renderer.readRenderTargetPixelsAsync(target, 0, 0, width, height, buffer, undefined, textureIndex);
|
|
30
|
+
});
|
|
31
|
+
return pending.then((value) => {
|
|
32
|
+
if (value !== buffer)
|
|
33
|
+
throw new Error("Float target read did not return its buffer");
|
|
34
|
+
return buffer;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/** Synchronous authoring/diagnostic read. Three restores the raw resolve
|
|
38
|
+
* framebuffer, not a current target's multisample attachment, after reading.
|
|
39
|
+
* Submit from a neutral target and let setRenderTarget restore the actual
|
|
40
|
+
* attachment; otherwise the next draw can resolve stale samples over new data.
|
|
41
|
+
* This also avoids restoring cube/mip framebuffer arrays as a framebuffer. */
|
|
42
|
+
export function readTargetPixelsScoped(renderer, target, width, height, buffer, textureIndex = 0) {
|
|
43
|
+
renderTargetScope(renderer, () => {
|
|
44
|
+
renderer.setRenderTarget(null);
|
|
45
|
+
renderer.readRenderTargetPixels(target, 0, 0, width, height, buffer, undefined, textureIndex);
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/spring.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ThreeElements } from "@react-three/fiber";
|
|
2
|
+
import type { WithAnimated } from "@react-spring/three";
|
|
3
|
+
/** Explicit Three hosts driven by React Spring's normal scheduler. Updating a
|
|
4
|
+
* Three prop invalidates its Fiber root; DOM-only springs do not render a scene.
|
|
5
|
+
* Does not install a global clock, call useFrame, or repair another module's
|
|
6
|
+
* scheduler changes. Avoid runtime imports of @react-spring/three alongside it. */
|
|
7
|
+
export declare function createFiberSpringHost<T extends keyof ThreeElements>(primitives: readonly T[]): Pick<WithAnimated, T>;
|
|
8
|
+
/** Small default host; opt into other Fiber primitives with createFiberSpringHost. */
|
|
9
|
+
export declare const animated: Pick<WithAnimated, "group" | "mesh">;
|
|
10
|
+
export { useSpring, easings } from "@react-spring/web";
|
package/dist/spring.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { applyProps } from "@react-three/fiber";
|
|
2
|
+
import { createHost } from "@react-spring/animated";
|
|
3
|
+
/** Explicit Three hosts driven by React Spring's normal scheduler. Updating a
|
|
4
|
+
* Three prop invalidates its Fiber root; DOM-only springs do not render a scene.
|
|
5
|
+
* Does not install a global clock, call useFrame, or repair another module's
|
|
6
|
+
* scheduler changes. Avoid runtime imports of @react-spring/three alongside it. */
|
|
7
|
+
export function createFiberSpringHost(primitives) {
|
|
8
|
+
return createHost([...primitives], { applyAnimatedValues: applyProps })
|
|
9
|
+
.animated;
|
|
10
|
+
}
|
|
11
|
+
/** Small default host; opt into other Fiber primitives with createFiberSpringHost. */
|
|
12
|
+
export const animated = createFiberSpringHost(["mesh", "group"]);
|
|
13
|
+
export { useSpring, easings } from "@react-spring/web";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absolutejs/rendering",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Render-destination coverage policies and callback-preserving material ownership for Three.js applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./spring": {
|
|
15
|
+
"types": "./dist/spring.d.ts",
|
|
16
|
+
"import": "./dist/spring.js",
|
|
17
|
+
"default": "./dist/spring.js"
|
|
13
18
|
}
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
@@ -31,16 +36,48 @@
|
|
|
31
36
|
"build": "tsc -p tsconfig.json",
|
|
32
37
|
"test": "bun test ./tests",
|
|
33
38
|
"check:package": "bun run build && bun run test",
|
|
34
|
-
"test:browser": "bun scripts/verify-browser.cjs"
|
|
39
|
+
"test:browser": "bun scripts/verify-browser.cjs",
|
|
40
|
+
"test:spring:browser": "bun scripts/verify-spring.cjs"
|
|
35
41
|
},
|
|
36
42
|
"peerDependencies": {
|
|
37
|
-
"three": ">=0.186.0 <0.187.0"
|
|
43
|
+
"three": ">=0.186.0 <0.187.0",
|
|
44
|
+
"react": ">=19.3.0 <20",
|
|
45
|
+
"@react-three/fiber": ">=9.8.2 <10",
|
|
46
|
+
"@react-spring/animated": ">=10.1.2 <11",
|
|
47
|
+
"@react-spring/web": ">=10.1.2 <11",
|
|
48
|
+
"@react-spring/three": ">=10.1.2 <11"
|
|
38
49
|
},
|
|
39
50
|
"devDependencies": {
|
|
40
51
|
"three": "0.186.1",
|
|
41
52
|
"@types/three": "0.186.0",
|
|
42
53
|
"@types/bun": "1.4.2",
|
|
43
54
|
"typescript": "5.9.3",
|
|
44
|
-
"playwright": "1.61.1"
|
|
55
|
+
"playwright": "1.61.1",
|
|
56
|
+
"react": "19.3.0",
|
|
57
|
+
"react-dom": "19.3.0",
|
|
58
|
+
"@types/react": "19.3.0",
|
|
59
|
+
"@types/react-dom": "19.3.0",
|
|
60
|
+
"@react-three/fiber": "9.8.2",
|
|
61
|
+
"@react-spring/animated": "10.1.2",
|
|
62
|
+
"@react-spring/web": "10.1.2",
|
|
63
|
+
"@react-spring/three": "10.1.2",
|
|
64
|
+
"@react-spring/shared": "10.1.2"
|
|
65
|
+
},
|
|
66
|
+
"peerDependenciesMeta": {
|
|
67
|
+
"react": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
70
|
+
"@react-three/fiber": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"@react-spring/animated": {
|
|
74
|
+
"optional": true
|
|
75
|
+
},
|
|
76
|
+
"@react-spring/web": {
|
|
77
|
+
"optional": true
|
|
78
|
+
},
|
|
79
|
+
"@react-spring/three": {
|
|
80
|
+
"optional": true
|
|
81
|
+
}
|
|
45
82
|
}
|
|
46
83
|
}
|