orbix-engine 1.0.0 → 1.0.1

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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +961 -0
  3. package/package.json +3 -2
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Orbix Engine Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,961 @@
1
+ # Orbix Engine
2
+
3
+ **GPU-accelerated WebGL engine** — fluid simulations, particle systems, post-processing, physics, audio, VR/AR, and more. One script tag, zero dependencies, works on desktop and mobile.
4
+
5
+ ```html
6
+ <script src="https://unpkg.com/orbix-engine@1.0.1/dist/orbix.min.js"></script>
7
+ ```
8
+
9
+ ```html
10
+ <script src="https://cdn.jsdelivr.net/npm/orbix-engine@1.0.1/dist/orbix.min.js"></script>
11
+ ```
12
+
13
+ ---
14
+
15
+ ## Hello World
16
+
17
+ ```html
18
+ <!DOCTYPE html>
19
+ <html>
20
+ <head>
21
+ <style>* { margin: 0 } body { background: #000; overflow: hidden }</style>
22
+ </head>
23
+ <body>
24
+ <script src="https://unpkg.com/orbix-engine@1.0.1/dist/orbix.min.js"></script>
25
+ <script>
26
+ Orbix.ready().then(function() {
27
+
28
+ var cube = new Mesh(
29
+ new BoxGeometry(2, 2, 2),
30
+ new Shader('ColorMaterial', {
31
+ unique: true,
32
+ color: { value: new Color(0.2, 0.5, 1.0) },
33
+ alpha: { value: 1.0 }
34
+ })
35
+ );
36
+
37
+ World.SCENE.add(cube);
38
+ World.CAMERA.position.z = 6;
39
+
40
+ Render.start(function() {
41
+ cube.rotation.x += 0.01;
42
+ cube.rotation.y += 0.02;
43
+ });
44
+
45
+ });
46
+ </script>
47
+ </body>
48
+ </html>
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Install
54
+
55
+ | Method | URL |
56
+ |--------|-----|
57
+ | unpkg CDN | `https://unpkg.com/orbix-engine@1.0.1/dist/orbix.min.js` |
58
+ | jsDelivr CDN | `https://cdn.jsdelivr.net/npm/orbix-engine@1.0.1/dist/orbix.min.js` |
59
+ | npm | `npm install orbix-engine` |
60
+
61
+ ### npm / bundler
62
+
63
+ ```js
64
+ import Orbix, { Mesh, BoxGeometry, Shader, Color, Render, World } from 'orbix-engine';
65
+
66
+ Orbix.ready().then(() => { /* ... */ });
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Core Concepts
72
+
73
+ ### `Orbix.ready()`
74
+
75
+ All engine use must happen inside the `.ready()` promise. The engine boots asynchronously (WebGL context, shader compilation, internal asset loading). Calling it multiple times is safe — each call gets its own Promise.
76
+
77
+ ```js
78
+ Orbix.ready().then(function() {
79
+ // safe to use any Orbix class here
80
+ });
81
+
82
+ // or async/await
83
+ async function main() {
84
+ await Orbix.ready();
85
+ // ...
86
+ }
87
+ ```
88
+
89
+ ### `Orbix.check()`
90
+
91
+ Returns support information before loading the full bundle:
92
+
93
+ ```js
94
+ var info = Orbix.check();
95
+ // { supported: true, webgl: true, mobile: false, gpu: 'Apple M2', tier: 'high' }
96
+ ```
97
+
98
+ ---
99
+
100
+ ## API Reference
101
+
102
+ ### Globals available after `ready()`
103
+
104
+ All classes and constants listed below are also available directly on `window` (or the `Orbix` namespace). You can use `new Mesh(...)` or `new Orbix.Mesh(...)` interchangeably.
105
+
106
+ ---
107
+
108
+ ### Boot
109
+
110
+ | Symbol | Description |
111
+ |--------|-------------|
112
+ | `Orbix.ready()` | Returns `Promise` — resolves when engine is fully booted |
113
+ | `Orbix.check()` | Returns `{ supported, webgl, mobile, gpu, tier }` — safe to call before load |
114
+ | `Orbix.VERSION` | Semver string |
115
+ | `Orbix.supported` | Boolean — `false` if WebGL unavailable |
116
+
117
+ ---
118
+
119
+ ### World & Rendering
120
+
121
+ | Symbol | Description |
122
+ |--------|-------------|
123
+ | `World.SCENE` | The root `Scene` — add your objects here |
124
+ | `World.CAMERA` | Default `PerspectiveCamera` |
125
+ | `World.RENDERER` | The `Renderer` instance |
126
+ | `World.NUKE` | Post-processing pipeline |
127
+ | `World.ELEMENT` | The `<canvas>` DOM element |
128
+ | `Render.start(fn)` | Register a per-frame callback `(time, dt) => void` |
129
+ | `Render.stop(fn)` | Remove a callback |
130
+ | `Render.fps` | Current frames per second |
131
+
132
+ ```js
133
+ Render.start(function(time, dt) {
134
+ mesh.rotation.y += dt * 2;
135
+ });
136
+ ```
137
+
138
+ ---
139
+
140
+ ### 3D Objects
141
+
142
+ | Class | Constructor | Description |
143
+ |-------|-------------|-------------|
144
+ | `Mesh` | `(geometry, shader)` | A visible 3D object |
145
+ | `Group` | `()` | Container to transform multiple objects together |
146
+ | `Scene` | `()` | Root container (use `World.SCENE` by default) |
147
+ | `Points` | `(geometry, shader)` | Point cloud |
148
+ | `Line3D` | `(geometry, shader)` | Line strip |
149
+ | `Object3D` | `()` | Base class — position, rotation, scale, matrix |
150
+
151
+ Every 3D object has:
152
+
153
+ ```js
154
+ mesh.position.set(x, y, z)
155
+ mesh.rotation.x = Math.PI / 4
156
+ mesh.scale.setScalar(2)
157
+ mesh.visible = false
158
+ mesh.add(child)
159
+ mesh.remove(child)
160
+ mesh.traverse(fn)
161
+ mesh.dispose()
162
+ ```
163
+
164
+ ---
165
+
166
+ ### Geometry
167
+
168
+ | Class | Constructor |
169
+ |-------|-------------|
170
+ | `PlaneGeometry` | `(width, height, widthSegs, heightSegs)` |
171
+ | `BoxGeometry` | `(width, height, depth, wSegs, hSegs, dSegs)` |
172
+ | `SphereGeometry` | `(radius, widthSegs, heightSegs)` |
173
+ | `CylinderGeometry` | `(radiusTop, radiusBottom, height, radialSegs)` |
174
+ | `IcosahedronGeometry` | `(radius, detail)` |
175
+ | `Geometry` | Base — set `attributes` and `index` manually |
176
+
177
+ ```js
178
+ // Custom geometry
179
+ var geo = new Geometry();
180
+ geo.addAttribute('position', new GeometryAttribute(new Float32Array([...]), 3));
181
+ geo.setIndex([0, 1, 2]);
182
+ geo.computeVertexNormals();
183
+ ```
184
+
185
+ **Loaders:**
186
+
187
+ ```js
188
+ // Load from web worker thread (non-blocking)
189
+ GeomThread.loadGeometry('/model.bin').then(function(geo) { ... });
190
+
191
+ // Draco-compressed
192
+ DracoThread.decode(buffer).then(function(geo) { ... });
193
+
194
+ // GLTF
195
+ var loader = new GLTFLoader();
196
+ loader.load('/scene.glb', function(gltf) {
197
+ World.SCENE.add(gltf.scene);
198
+ });
199
+
200
+ // Spline paths
201
+ var spline = new SplineGen(points, closed);
202
+ var pt = spline.getPoint(0.5); // Vector3 at t=0.5
203
+ ```
204
+
205
+ ---
206
+
207
+ ### Shaders & Materials
208
+
209
+ #### Built-in: `ColorMaterial`
210
+
211
+ The simplest shader — a flat color with optional transparency.
212
+
213
+ ```js
214
+ new Shader('ColorMaterial', {
215
+ unique: true, // each mesh gets its own uniform copy
216
+ color: { value: new Color(1, 0, 0) }, // RGB 0–1
217
+ alpha: { value: 1.0 }
218
+ })
219
+ ```
220
+
221
+ #### Custom GLSL via `Shaders.parse()`
222
+
223
+ Register a custom shader at runtime from a JavaScript string and use it like any built-in:
224
+
225
+ ```js
226
+ Shaders.parse(`
227
+ {@}MyShader.glsl{@}
228
+ #!ATTRIBUTES
229
+
230
+ #!UNIFORMS
231
+ uniform float uTime;
232
+ uniform vec3 uColor;
233
+
234
+ #!VARYINGS
235
+ varying vec2 vUv;
236
+
237
+ #!SHADER: MyShader.Vertex
238
+ void main() {
239
+ vUv = uv;
240
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
241
+ }
242
+
243
+ #!SHADER: MyShader.Fragment
244
+ void main() {
245
+ gl_FragColor = vec4(uColor, 1.0);
246
+ }
247
+ `, 'MyShader.glsl');
248
+
249
+ var mesh = new Mesh(
250
+ new SphereGeometry(1, 32, 32),
251
+ new Shader('MyShader', {
252
+ unique: true,
253
+ uTime: { value: 0 },
254
+ uColor: { value: new Color(0.2, 0.8, 1.0) }
255
+ })
256
+ );
257
+ World.SCENE.add(mesh);
258
+
259
+ Render.start(function(time) {
260
+ mesh.shader.uniforms.uTime.value = time;
261
+ });
262
+ ```
263
+
264
+ #### `PBRShader` — physically based
265
+
266
+ ```js
267
+ new PBRShader({
268
+ roughness: 0.4,
269
+ metalness: 0.8,
270
+ envMapIntensity: 1.0
271
+ })
272
+ ```
273
+
274
+ #### `ShaderVariants` — switch between presets
275
+
276
+ ```js
277
+ var variants = new ShaderVariants('ColorMaterial', {
278
+ hot: { color: { value: new Color(1, 0.2, 0) } },
279
+ cool: { color: { value: new Color(0, 0.5, 1) } }
280
+ });
281
+ mesh.shader = variants.use('cool');
282
+ ```
283
+
284
+ ---
285
+
286
+ ### Math
287
+
288
+ #### Vectors
289
+
290
+ ```js
291
+ var v = new Vector3(1, 2, 3);
292
+ v.add(new Vector3(0, 1, 0)); // chainable
293
+ v.normalize();
294
+ v.length();
295
+ v.dot(other);
296
+ v.cross(other);
297
+ v.lerp(target, 0.5);
298
+ v.applyMatrix4(matrix);
299
+ v.clone();
300
+ ```
301
+
302
+ `Vector2`, `Vector3`, `Vector4` all follow the same pattern.
303
+
304
+ #### Color
305
+
306
+ ```js
307
+ var c = new Color(1, 0.5, 0); // RGB 0–1
308
+ c.setHex(0xff8800);
309
+ c.setHSL(0.05, 1.0, 0.5);
310
+ c.lerp(other, t);
311
+ ```
312
+
313
+ #### Quaternion / Euler / Matrix
314
+
315
+ ```js
316
+ var q = new Quaternion();
317
+ q.setFromEuler(new Euler(0, Math.PI, 0));
318
+ q.slerp(target, 0.1);
319
+
320
+ var m = new Matrix4();
321
+ m.makeRotationFromQuaternion(q);
322
+ m.makeTranslation(x, y, z);
323
+ ```
324
+
325
+ #### `MathUtils`
326
+
327
+ ```js
328
+ MathUtils.radians(90) // 1.5707...
329
+ MathUtils.lerp(0, 10, 0.5) // 5
330
+ MathUtils.clamp(val, 0, 1)
331
+ MathUtils.range(val, 0, 1, -100, 100)
332
+ MathUtils.smoothStep(0, 1, val)
333
+ MathUtils.randFloat(0, 1)
334
+ MathUtils.randInt(0, 10)
335
+ ```
336
+
337
+ ---
338
+
339
+ ### Textures
340
+
341
+ ```js
342
+ // From URL (cached)
343
+ var tex = Utils3D.getTexture('/path/to/image.jpg');
344
+
345
+ // Repeat-wrap texture
346
+ var rep = Utils3D.getRepeatTexture('/tile.jpg');
347
+
348
+ // Cubemap
349
+ var env = Utils3D.loadCubemap(['+x.jpg', '-x.jpg', '+y.jpg', '-y.jpg', '+z.jpg', '-z.jpg']);
350
+
351
+ // Data texture (Float32 data → GPU)
352
+ var data = Utils3D.createDataTexture(float32Array, width, height);
353
+
354
+ // RenderTarget (render-to-texture)
355
+ var rt = new RenderTarget(512, 512, { type: 'float' });
356
+
357
+ // Pooled RenderTargets (saves GC pressure)
358
+ var rt = RTPool.get(512, 512);
359
+ RTPool.release(rt);
360
+ ```
361
+
362
+ ---
363
+
364
+ ### Camera
365
+
366
+ ```js
367
+ // Default perspective camera
368
+ World.CAMERA.fov = 60;
369
+ World.CAMERA.position.z = 10;
370
+ World.CAMERA.lookAt(new Vector3(0, 0, 0));
371
+ World.CAMERA.updateProjectionMatrix();
372
+
373
+ // Orthographic
374
+ var ortho = new OrthographicCamera(-1, 1, 1, -1, 0.1, 100);
375
+
376
+ // VR / XR
377
+ var vrCam = new VRCamera();
378
+ vrCam.setFromXRFrame(frame, refSpace);
379
+
380
+ // Screen ↔ World projection
381
+ var screen = ScreenProjection.toScreen(worldPos, camera); // Vector2
382
+ var world = ScreenProjection.toWorld(screenPos, z, camera); // Vector3
383
+ ```
384
+
385
+ ---
386
+
387
+ ### Lighting
388
+
389
+ ```js
390
+ Lighting.setAmbient(new Color(0.1, 0.1, 0.1), 1.0);
391
+
392
+ var sun = new ShadowLight({
393
+ color: new Color(1, 0.95, 0.8),
394
+ intensity: 2.0,
395
+ shadow: { mapSize: new Vector2(2048, 2048) }
396
+ });
397
+ sun.castShadow = true;
398
+ World.SCENE.add(sun);
399
+ ```
400
+
401
+ ---
402
+
403
+ ### Post-Processing (Nuke)
404
+
405
+ ```js
406
+ // Bloom
407
+ var bloom = new HydraBloom({ strength: 1.5, radius: 0.4, threshold: 0.7 });
408
+ World.NUKE.add(bloom);
409
+
410
+ // Unreal-style bloom
411
+ var unrealBloom = new UnrealBloom({ strength: 2.0, radius: 0.3 });
412
+ World.NUKE.add(unrealBloom);
413
+
414
+ // Anti-aliasing
415
+ var fxaa = new FXAA();
416
+ World.NUKE.add(fxaa);
417
+
418
+ // Lens streaks
419
+ var streak = new HydraLensStreak();
420
+ World.NUKE.add(streak);
421
+
422
+ // Volumetric light shafts
423
+ var vol = new VolumetricLight({ density: 0.96, decay: 0.94, weight: 0.4, samples: 100 });
424
+ World.NUKE.add(vol);
425
+
426
+ // Custom fullscreen shader pass
427
+ var pass = new NukePass('MyShader', {
428
+ uTexture: { value: someTexture },
429
+ uIntensity: { value: 0.5 }
430
+ });
431
+ World.NUKE.add(pass);
432
+
433
+ // Mirror reflection
434
+ var mirror = new Mirror({ clipBias: 0.003 });
435
+ World.SCENE.add(mirror);
436
+ ```
437
+
438
+ ---
439
+
440
+ ### Fluid Simulation
441
+
442
+ ```js
443
+ // Standalone fluid (manage yourself)
444
+ var fluid = new Fluid(128, 512); // simSize, dyeSize
445
+
446
+ Render.start(function(t, dt) {
447
+ fluid.splat(Mouse.nX * 0.5 + 0.5, 0.5 - Mouse.nY * 0.5,
448
+ Mouse.vX * 20, -Mouse.vY * 20,
449
+ new Color(1, 0.5, 0));
450
+ fluid.update(dt);
451
+
452
+ mesh.shader.uniforms.uFluid.value = fluid.texture;
453
+ });
454
+
455
+ // Mouse-driven fluid (automatic)
456
+ var mouseFluid = new MouseFluid();
457
+ mouseFluid.applyTo(mesh); // links fluid texture to mesh's shader
458
+ Render.start(function() { mouseFluid.update(); });
459
+
460
+ // Full fluid scene (mesh + sim pre-wired)
461
+ var scene = new FluidScene({ simSize: 128, dyeSize: 512 });
462
+ World.SCENE.add(scene.mesh);
463
+ Render.start(function(t, dt) { scene.update(dt); });
464
+ ```
465
+
466
+ ---
467
+
468
+ ### Particles — Antimatter
469
+
470
+ GPU-based particle system simulated on the graphics card.
471
+
472
+ ```js
473
+ var particles = new Antimatter({
474
+ count: 100000,
475
+ size: 2.0,
476
+ blending: 'additive',
477
+ spawner: new AntimatterSpawn({ rate: 1000, burst: false }),
478
+ behavior: 'default'
479
+ });
480
+ World.SCENE.add(particles.mesh);
481
+
482
+ // Manual spawn
483
+ particles.spawn(
484
+ new Vector3(0, 0, 0), // position
485
+ new Vector3(0, 1, 0) // velocity
486
+ );
487
+
488
+ Render.start(function() { /* Antimatter auto-updates via Render loop */ });
489
+ ```
490
+
491
+ **Spline particles** — particles that travel along a path:
492
+
493
+ ```js
494
+ var path = new SplineGen([p0, p1, p2, p3], false);
495
+ var ribbon = new SplineParticles(path, { count: 500, size: 1.5 });
496
+ World.SCENE.add(ribbon.mesh);
497
+ Render.start(function(t, dt) { ribbon.update(dt); });
498
+ ```
499
+
500
+ ---
501
+
502
+ ### Instancing & Batching
503
+
504
+ Draw thousands of meshes in a single draw call:
505
+
506
+ ```js
507
+ // InstanceMesh — each instance can have its own matrix + color
508
+ var inst = new InstanceMesh(
509
+ new BoxGeometry(0.5, 0.5, 0.5),
510
+ new Shader('ColorMaterial', { color: { value: new Color(1, 1, 1) } }),
511
+ 10000
512
+ );
513
+
514
+ var m = new Matrix4();
515
+ for (var i = 0; i < 10000; i++) {
516
+ m.makeTranslation(
517
+ MathUtils.randFloat(-10, 10),
518
+ MathUtils.randFloat(-10, 10),
519
+ MathUtils.randFloat(-10, 10)
520
+ );
521
+ inst.setMatrixAt(i, m);
522
+ inst.setColorAt(i, new Color(Math.random(), Math.random(), Math.random()));
523
+ }
524
+ inst.update();
525
+ World.SCENE.add(inst.mesh);
526
+
527
+ // MeshBatch — add/remove at runtime
528
+ var batch = new MeshBatch(geo, shader, 500);
529
+ var id = batch.add(new Matrix4(), new Color(1, 0, 0));
530
+ batch.remove(id);
531
+ batch.update();
532
+ ```
533
+
534
+ ---
535
+
536
+ ### Mouse & Interaction
537
+
538
+ ```js
539
+ // Normalized mouse position (-1 to +1)
540
+ Mouse.nX // horizontal
541
+ Mouse.nY // vertical
542
+
543
+ // Raw pixel position
544
+ Mouse.x
545
+ Mouse.y
546
+
547
+ // Velocity (per frame delta)
548
+ Mouse.vX
549
+ Mouse.vY
550
+
551
+ // Is mouse/finger down
552
+ Mouse.down
553
+
554
+ // Events
555
+ Mouse.on('down', function() { ... });
556
+ Mouse.on('up', function() { ... });
557
+ Mouse.on('move', function() { ... });
558
+
559
+ // Pointer-events-style (touch + mouse unified)
560
+ Interaction.on('down', handler);
561
+ Interaction.on('up', handler);
562
+ Interaction.on('move', handler);
563
+ ```
564
+
565
+ **3D raycasting:**
566
+
567
+ ```js
568
+ var i3d = new Interaction3D(World.CAMERA, World.SCENE);
569
+ i3d.add(mesh);
570
+ i3d.on('click', function(obj) { console.log('clicked', obj); });
571
+ i3d.on('over', function(obj) { ... });
572
+ i3d.on('out', function(obj) { ... });
573
+
574
+ // Manual raycasting
575
+ var raycaster = new Raycaster();
576
+ raycaster.setFromCamera(new Vector2(Mouse.nX, -Mouse.nY), World.CAMERA);
577
+ var hits = raycaster.intersectObjects(World.SCENE.children, true);
578
+ ```
579
+
580
+ **Scroll:**
581
+
582
+ ```js
583
+ Scroll.y // current scroll Y
584
+ Scroll.delta // delta this frame
585
+ Scroll.on('scroll', function() { ... });
586
+ ```
587
+
588
+ **Keyboard:**
589
+
590
+ ```js
591
+ Keyboard.on('down', function(key, code) { ... });
592
+ Keyboard.isDown('Space'); // true/false
593
+ Keyboard.isDown(32); // by key code
594
+ ```
595
+
596
+ ---
597
+
598
+ ### Animation & Tweening
599
+
600
+ ```js
601
+ // TweenManager
602
+ TweenManager.to(mesh.position, { y: 5 }, 1.0, 'easeOutCubic');
603
+ TweenManager.to(shader.uniforms.uColor, { value: new Color(1, 0, 0) }, 0.5);
604
+ TweenManager.kill(mesh.position); // cancel
605
+
606
+ // One-liner shortcut
607
+ tween(mesh.rotation, { y: Math.PI * 2 }, 2.0, 'easeInOutQuad');
608
+
609
+ // TweenTimeline — sequence / overlap animations
610
+ var tl = new TweenTimeline({ loop: false });
611
+ tl.add(TweenManager.to(mesh.position, { y: 3 }, 0.5), 0.0);
612
+ tl.add(TweenManager.to(mesh.scale, { x: 2 }, 0.5), 0.3);
613
+ tl.play();
614
+
615
+ // CSS transitions
616
+ var css = new CSSTransition(element, { duration: 0.4, ease: 'easeOutQuad' });
617
+ css.to({ opacity: 0, transform: 'translateY(-20px)' });
618
+ ```
619
+
620
+ Ease names: `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeInOutQuart`, `easeOutBack`, `easeInOutElastic`, `easeOutExpo`, `easeInOutBounce`
621
+
622
+ ---
623
+
624
+ ### Audio
625
+
626
+ ```js
627
+ // Spatial audio (WebAudio API)
628
+ var sfx = new Audio3D('/click.mp3', { volume: 0.8, loop: false });
629
+ sfx.position.copy(mesh.position);
630
+ sfx.play();
631
+
632
+ // Sound effects controller (named sound bank)
633
+ var sfxCtrl = new SFXController({
634
+ click: '/sounds/click.mp3',
635
+ whoosh: '/sounds/whoosh.mp3'
636
+ });
637
+ sfxCtrl.play('click', { volume: 0.5, pitch: 1.2 });
638
+
639
+ // Master volume
640
+ GlobalAudio3D.setVolume(0.5);
641
+ GlobalAudio3D.mute();
642
+ GlobalAudio3D.unmute();
643
+
644
+ // Raw Web Audio access
645
+ var ctx = WebAudio.context;
646
+ var analyser = WebAudio.createAnalyser();
647
+ var freqData = WebAudio.getFrequencyData(analyser); // Uint8Array
648
+ ```
649
+
650
+ ---
651
+
652
+ ### Video
653
+
654
+ ```js
655
+ var video = new Video('/clip.mp4', { autoplay: true, loop: true, muted: true, playsInline: true });
656
+ video.play();
657
+
658
+ var vtex = new VideoTexture(video);
659
+
660
+ // Use as shader texture
661
+ var mesh = new Mesh(
662
+ new PlaneGeometry(16, 9),
663
+ new Shader('MyVideoShader', {
664
+ unique: true,
665
+ uVideo: { value: vtex }
666
+ })
667
+ );
668
+
669
+ Render.start(function() {
670
+ vtex.update(); // push new frame to GPU
671
+ });
672
+
673
+ // Webcam
674
+ var cam = new Webcam({ facingMode: 'user', width: 1280, height: 720 });
675
+ cam.start().then(function() {
676
+ var tex = cam.texture;
677
+ });
678
+ ```
679
+
680
+ ---
681
+
682
+ ### Text (WebGL)
683
+
684
+ ```js
685
+ var label = new Text3D('Hello World', {
686
+ font: '/fonts/Inter.json',
687
+ size: 0.5,
688
+ color: new Color(1, 1, 1),
689
+ align: 'center'
690
+ });
691
+ World.SCENE.add(label);
692
+ label.setText('New Text');
693
+
694
+ var { width, height } = label.measure();
695
+ ```
696
+
697
+ ---
698
+
699
+ ### Post — Scene Fragments (`Frag3D`)
700
+
701
+ Frag3D is a composable scene unit — encapsulate a sub-scene with its own lifecycle:
702
+
703
+ ```js
704
+ class MyFragment extends Frag3D {
705
+ init() {
706
+ this.mesh = new Mesh(new BoxGeometry(1, 1, 1), new Shader('ColorMaterial', {
707
+ unique: true, color: { value: new Color(1, 0, 0) }, alpha: { value: 1 }
708
+ }));
709
+ this.add(this.mesh);
710
+ }
711
+ update(dt) {
712
+ this.mesh.rotation.y += dt;
713
+ }
714
+ }
715
+
716
+ var frag = new MyFragment();
717
+ SceneLayout.add(frag);
718
+ World.SCENE.add(frag);
719
+ Render.start(function(t, dt) { SceneLayout.update(dt); });
720
+
721
+ frag.show(0.5); // fade in over 0.5s
722
+ frag.hide(0.5); // fade out
723
+ ```
724
+
725
+ ---
726
+
727
+ ### Loading Assets
728
+
729
+ ```js
730
+ // Non-blocking asset preload
731
+ AssetLoader.on('progress', function(pct) { console.log(pct * 100 + '%'); });
732
+ AssetLoader.on('complete', function() { /* all done */ });
733
+
734
+ AssetLoader.loadAssets({
735
+ textures: ['/diffuse.jpg', '/normal.jpg'],
736
+ audio: ['/music.mp3'],
737
+ json: ['/data.json']
738
+ });
739
+
740
+ // Individual loads
741
+ Assets.loadJSON('/config.json').then(function(data) { ... });
742
+ Assets.loadText('/shader.glsl').then(function(src) { ... });
743
+
744
+ // KTX2 compressed textures (GPU-native, fastest load)
745
+ var ktx = new Ktx2Transcoder();
746
+ ktx.transcode(buffer).then(function(texture) { ... });
747
+ ```
748
+
749
+ ---
750
+
751
+ ### Multiplayer / Networking
752
+
753
+ ```js
754
+ var conn = Multiplayer.connect('wss://yourserver.com');
755
+ conn.on('connect', function() { conn.send('hello', { id: 'player1' }); });
756
+ conn.on('message', function(data) { ... });
757
+
758
+ // Synchronized object positions
759
+ var sync = new SynchronizedObjects();
760
+ sync.add(mesh, 'object-id');
761
+ Render.start(function(t, dt) { sync.update(dt); });
762
+ ```
763
+
764
+ ---
765
+
766
+ ### VR / AR
767
+
768
+ ```js
769
+ // Check support
770
+ XRDeviceManager.isSupported('immersive-vr').then(function(ok) {
771
+ if (ok) {
772
+ var btn = document.createElement('button');
773
+ btn.textContent = 'Enter VR';
774
+ btn.onclick = function() {
775
+ XRDeviceManager.requestSession('immersive-vr').then(function(session) {
776
+ var vrCam = new VRCamera();
777
+ var vrRenderer = new VRRenderer(World.RENDERER, session);
778
+ var vrInput = new VRInput(session);
779
+
780
+ session.requestAnimationFrame(function frame(t, xrFrame) {
781
+ vrCam.setFromXRFrame(xrFrame, refSpace);
782
+ vrInput.update(xrFrame);
783
+ vrRenderer.render(World.SCENE, vrCam, xrFrame);
784
+ session.requestAnimationFrame(frame);
785
+ });
786
+ });
787
+ };
788
+ document.body.appendChild(btn);
789
+ }
790
+ });
791
+
792
+ // AR: place object at tap position
793
+ XRDeviceManager.isSupported('immersive-ar').then(function(ok) {
794
+ ARUtils.createSession().then(function(session) { ... });
795
+ });
796
+ ```
797
+
798
+ ---
799
+
800
+ ### GPU & Performance
801
+
802
+ ```js
803
+ // GPU info (before anything renders)
804
+ console.log(GPU.vendor); // 'Apple'
805
+ console.log(GPU.tier); // 0 = low, 1 = mid, 2 = high
806
+ console.log(GPU.webgl2); // true/false
807
+ console.log(GPU.isMobile); // true/false
808
+
809
+ // Adaptive quality
810
+ if (GPU.tier < 1) {
811
+ World.RENDERER.setPixelRatio(1);
812
+ bloom.enabled = false;
813
+ }
814
+
815
+ // Frame timing
816
+ Performance.on('low-fps', function(fps) {
817
+ console.warn('FPS dropped to', fps);
818
+ });
819
+ ```
820
+
821
+ ---
822
+
823
+ ### Device Detection
824
+
825
+ ```js
826
+ Device.mobile // false | { phone, tablet, pwa, native }
827
+ Device.system.os // 'ios' | 'android' | 'windows' | 'macos' | 'linux'
828
+ Device.system.browser // 'chrome' | 'safari' | 'firefox' | ...
829
+ Device.system.retina // true/false
830
+ Device.pixelRatio // 1 | 2 | 3
831
+ Device.touchCapable // true/false
832
+ ```
833
+
834
+ ---
835
+
836
+ ### Threading
837
+
838
+ Off-main-thread work via Web Workers:
839
+
840
+ ```js
841
+ var worker = Thread.create(function() {
842
+ self.onmessage = function(e) {
843
+ // do heavy computation
844
+ var result = e.data.map(function(n) { return n * n; });
845
+ self.postMessage(result);
846
+ };
847
+ });
848
+
849
+ Thread.post(worker, bigArray, [bigArray.buffer]);
850
+ worker.onmessage = function(e) {
851
+ console.log('result:', e.data);
852
+ };
853
+ ```
854
+
855
+ ---
856
+
857
+ ### Debug
858
+
859
+ ```js
860
+ Dev.enabled = true;
861
+
862
+ // Helpers
863
+ World.SCENE.add(Dev.grid(World.SCENE, 10, 10)); // grid floor
864
+ World.SCENE.add(Dev.axes(2)); // XYZ axes
865
+ document.body.appendChild(Dev.stats()); // FPS/MS/MB panel
866
+
867
+ Dev.log('mesh', mesh);
868
+ Dev.warn('shader missing uniform');
869
+ Dev.error('fatal:', err);
870
+ ```
871
+
872
+ ---
873
+
874
+ ### State Management (App)
875
+
876
+ ```js
877
+ AppState.set('score', 0);
878
+ AppState.get('score'); // 0
879
+
880
+ // Reactive — callback fires whenever value changes
881
+ AppState.on('score', function(val) {
882
+ console.log('score changed to', val);
883
+ });
884
+
885
+ // Scoped local state (component-level)
886
+ var state = AppState.createLocal({ count: 0, active: true });
887
+ state.count++;
888
+
889
+ // Storage (localStorage wrapper)
890
+ Storage.set('prefs', { volume: 0.8 });
891
+ Storage.get('prefs'); // { volume: 0.8 }
892
+ ```
893
+
894
+ ---
895
+
896
+ ### Helper Factories
897
+
898
+ Convenience shortcuts on the `Orbix` namespace:
899
+
900
+ ```js
901
+ // Full scene setup in one call
902
+ var { scene, camera, nuke, renderer, element } = Orbix.createScene();
903
+
904
+ // Fluid simulation
905
+ var fluid = Orbix.createFluid({ simSize: 128, dyeSize: 512 });
906
+
907
+ // MouseFluid
908
+ var mf = Orbix.createMouseFluid();
909
+
910
+ // Particle system
911
+ var particles = Orbix.createAntimatter({ count: 50000 });
912
+
913
+ // Post-processing pass
914
+ var pass = Orbix.createNukePass('ChromaticAberration', { uAmount: { value: 0.005 } });
915
+
916
+ // Texture
917
+ var tex = Orbix.getTexture('/img.jpg');
918
+ ```
919
+
920
+ ---
921
+
922
+ ## TypeScript
923
+
924
+ Full type definitions are included (`dist/orbix.d.ts`):
925
+
926
+ ```ts
927
+ import Orbix, {
928
+ Mesh, BoxGeometry, Shader, Color,
929
+ Render, World, Mouse,
930
+ Fluid, Antimatter, HydraBloom
931
+ } from 'orbix-engine';
932
+
933
+ Orbix.ready().then(() => {
934
+ const mesh = new Mesh(
935
+ new BoxGeometry(1, 1, 1),
936
+ new Shader('ColorMaterial', {
937
+ unique: true,
938
+ color: { value: new Color(0.2, 0.5, 1) },
939
+ alpha: { value: 1 }
940
+ })
941
+ );
942
+ World.SCENE.add(mesh);
943
+ });
944
+ ```
945
+
946
+ ---
947
+
948
+ ## Files
949
+
950
+ | File | Size | Description |
951
+ |------|------|-------------|
952
+ | `dist/orbix.min.js` | ~1.9 MB | **Production CDN build** — use this |
953
+ | `dist/orbix.js` | ~3.0 MB | Development build (unminified) |
954
+ | `dist/orbix.esm.js` | 11 KB | ESM loader / named exports |
955
+ | `dist/orbix.d.ts` | 60 KB | Full TypeScript definitions |
956
+
957
+ ---
958
+
959
+ ## License
960
+
961
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orbix-engine",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Orbix — GPU-accelerated WebGL engine with fluid simulations, particle systems, and post-processing. Works on desktop & mobile.",
5
5
  "main": "dist/orbix.js",
6
6
  "module": "dist/orbix.esm.js",
@@ -9,7 +9,8 @@
9
9
  "types": "dist/orbix.d.ts",
10
10
  "files": [
11
11
  "dist/",
12
- "LICENSE"
12
+ "LICENSE",
13
+ "README.md"
13
14
  ],
14
15
  "scripts": {
15
16
  "build": "python build.py",