@chromatic-coherence/generative-engine 1.0.1 → 1.0.3
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/world.d.ts +7 -0
- package/dist/world.js +32 -4
- package/package.json +1 -1
package/dist/world.d.ts
CHANGED
|
@@ -251,7 +251,14 @@ export declare class World {
|
|
|
251
251
|
private drawPts;
|
|
252
252
|
private drawRibbons;
|
|
253
253
|
private renderFrame;
|
|
254
|
+
private frameFn;
|
|
255
|
+
private pausedByUser;
|
|
254
256
|
start(): void;
|
|
257
|
+
/** Freeze the frame loop, keeping every GPU resource warm — the cheap way to park an
|
|
258
|
+
* off-screen world. resume() picks the motion back up instantly; nothing rebuilds. */
|
|
259
|
+
pause(): void;
|
|
260
|
+
/** Wake a pause()d world — the loop continues from where the clock left off. */
|
|
261
|
+
resume(): void;
|
|
255
262
|
/** Render one deterministic frame at time t (no loop) — stills, tests, screenshots. */
|
|
256
263
|
settle(t: number): void;
|
|
257
264
|
/** Stop the world. `releaseContext: true` also LOSES the GL context immediately —
|
package/dist/world.js
CHANGED
|
@@ -109,6 +109,8 @@ export class World {
|
|
|
109
109
|
this.zNear = 24;
|
|
110
110
|
this.zFar = 6000;
|
|
111
111
|
this.inkCss = new Map();
|
|
112
|
+
this.frameFn = null;
|
|
113
|
+
this.pausedByUser = false;
|
|
112
114
|
this.canvas = o.canvas;
|
|
113
115
|
const gl = o.canvas.getContext("webgl2", { alpha: true, antialias: false, premultipliedAlpha: true });
|
|
114
116
|
if (!gl)
|
|
@@ -161,17 +163,23 @@ export class World {
|
|
|
161
163
|
this.shadowSoft = o.shadows.softness ?? 1.6;
|
|
162
164
|
this.shadowBias = o.shadows.bias ?? 0.0035;
|
|
163
165
|
}
|
|
164
|
-
|
|
165
|
-
//
|
|
166
|
+
{
|
|
167
|
+
// the shadow sampler must ALWAYS have a complete depth-comparable texture bound:
|
|
168
|
+
// an unbound sampler2DShadow invalidates the face program on some drivers and
|
|
169
|
+
// every solid silently vanishes. Shadows off => a 1x1 dummy depth texture.
|
|
170
|
+
// (Shadows on: a REAL depth texture — LINEAR gives free 2x2 hardware PCF per tap.)
|
|
171
|
+
const size = this.shadowsOn ? this.shadowSize : 1;
|
|
166
172
|
this.shadowTex = gl.createTexture();
|
|
167
173
|
gl.bindTexture(gl.TEXTURE_2D, this.shadowTex);
|
|
168
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT24,
|
|
174
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT24, size, size, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null);
|
|
169
175
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
170
176
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
171
177
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
172
178
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
173
179
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
|
|
174
180
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL);
|
|
181
|
+
}
|
|
182
|
+
if (this.shadowsOn) {
|
|
175
183
|
this.shadowFBO = gl.createFramebuffer();
|
|
176
184
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.shadowFBO);
|
|
177
185
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, this.shadowTex, 0);
|
|
@@ -732,9 +740,10 @@ export class World {
|
|
|
732
740
|
this.renderFrame(t, dt);
|
|
733
741
|
this.raf = !document.hidden ? requestAnimationFrame(frame) : 0;
|
|
734
742
|
};
|
|
743
|
+
this.frameFn = frame;
|
|
735
744
|
this.raf = requestAnimationFrame(frame);
|
|
736
745
|
const onVis = () => {
|
|
737
|
-
if (!document.hidden && !this.raf && !this.disposed) {
|
|
746
|
+
if (!document.hidden && !this.raf && !this.disposed && !this.pausedByUser) {
|
|
738
747
|
this.tPrev = performance.now();
|
|
739
748
|
this.raf = requestAnimationFrame(frame);
|
|
740
749
|
}
|
|
@@ -742,6 +751,25 @@ export class World {
|
|
|
742
751
|
document.addEventListener("visibilitychange", onVis);
|
|
743
752
|
this.cleanup.push(() => document.removeEventListener("visibilitychange", onVis));
|
|
744
753
|
}
|
|
754
|
+
/** Freeze the frame loop, keeping every GPU resource warm — the cheap way to park an
|
|
755
|
+
* off-screen world. resume() picks the motion back up instantly; nothing rebuilds. */
|
|
756
|
+
pause() {
|
|
757
|
+
this.pausedByUser = true;
|
|
758
|
+
if (this.raf) {
|
|
759
|
+
cancelAnimationFrame(this.raf);
|
|
760
|
+
this.raf = 0;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
/** Wake a pause()d world — the loop continues from where the clock left off. */
|
|
764
|
+
resume() {
|
|
765
|
+
if (this.disposed || !this.pausedByUser)
|
|
766
|
+
return;
|
|
767
|
+
this.pausedByUser = false;
|
|
768
|
+
if (this.frameFn && !this.raf && !document.hidden) {
|
|
769
|
+
this.tPrev = performance.now();
|
|
770
|
+
this.raf = requestAnimationFrame(this.frameFn);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
745
773
|
/** Render one deterministic frame at time t (no loop) — stills, tests, screenshots. */
|
|
746
774
|
settle(t) { this.renderFrame(t, 0); }
|
|
747
775
|
/** Stop the world. `releaseContext: true` also LOSES the GL context immediately —
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chromatic-coherence/generative-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "THE THIRD ENGINE — a zero-dependency WebGL2 graphics engine grown from generative-charts-3d: HDR + bloom + SSAO post chain, hardware-PCF shadow maps, a geometry stdlib, ribbon strokes, group transforms and morph targets. The charts API rides on top unchanged.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|