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.
- package/LICENSE +21 -0
- package/README.md +961 -0
- 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.
|
|
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",
|