three-rb 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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE +21 -0
- data/README.md +153 -0
- data/docs/browser-runtime.md +153 -0
- data/docs/implementation-plan.md +874 -0
- data/docs/loaded-assets-design.md +400 -0
- data/docs/next-work.md +107 -0
- data/docs/publishing.md +64 -0
- data/docs/release-readiness.md +83 -0
- data/examples/browser/README.md +54 -0
- data/examples/browser/assets/animated_triangle.gltf +123 -0
- data/examples/browser/assets/checker.svg +11 -0
- data/examples/browser/assets/compressed_triangle.gltf +74 -0
- data/examples/browser/assets/studio.hdr +5 -0
- data/examples/browser/assets/triangle.gltf +67 -0
- data/examples/browser/composition/README.md +35 -0
- data/examples/browser/composition/boot.mjs +6 -0
- data/examples/browser/composition/index.html +136 -0
- data/examples/browser/composition/main.rb +216 -0
- data/examples/browser/composition/smoke_test.mjs +266 -0
- data/examples/browser/cube/README.md +41 -0
- data/examples/browser/cube/boot.mjs +6 -0
- data/examples/browser/cube/index.html +142 -0
- data/examples/browser/cube/main.rb +62 -0
- data/examples/browser/cube/smoke_test.mjs +99 -0
- data/examples/browser/cubemap/README.md +23 -0
- data/examples/browser/cubemap/boot.mjs +6 -0
- data/examples/browser/cubemap/index.html +142 -0
- data/examples/browser/cubemap/main.rb +84 -0
- data/examples/browser/cubemap/smoke_test.mjs +91 -0
- data/examples/browser/gltf/README.md +23 -0
- data/examples/browser/gltf/boot.mjs +6 -0
- data/examples/browser/gltf/index.html +142 -0
- data/examples/browser/gltf/main.rb +105 -0
- data/examples/browser/gltf/smoke_test.mjs +162 -0
- data/examples/browser/picking/README.md +33 -0
- data/examples/browser/picking/boot.mjs +6 -0
- data/examples/browser/picking/index.html +142 -0
- data/examples/browser/picking/main.rb +113 -0
- data/examples/browser/picking/smoke_test.mjs +78 -0
- data/examples/browser/postprocessing/README.md +26 -0
- data/examples/browser/postprocessing/boot.mjs +6 -0
- data/examples/browser/postprocessing/index.html +142 -0
- data/examples/browser/postprocessing/main.rb +117 -0
- data/examples/browser/postprocessing/smoke_test.mjs +121 -0
- data/examples/browser/primitives/README.md +33 -0
- data/examples/browser/primitives/boot.mjs +6 -0
- data/examples/browser/primitives/index.html +142 -0
- data/examples/browser/primitives/main.rb +116 -0
- data/examples/browser/primitives/smoke_test.mjs +113 -0
- data/examples/browser/serialization/README.md +33 -0
- data/examples/browser/serialization/boot.mjs +6 -0
- data/examples/browser/serialization/index.html +142 -0
- data/examples/browser/serialization/main.rb +97 -0
- data/examples/browser/serialization/smoke_test.mjs +67 -0
- data/examples/browser/shared/boot.mjs +79 -0
- data/examples/browser/shared/smoke_test_helpers.mjs +151 -0
- data/examples/browser/textures/README.md +35 -0
- data/examples/browser/textures/boot.mjs +6 -0
- data/examples/browser/textures/index.html +142 -0
- data/examples/browser/textures/main.rb +142 -0
- data/examples/browser/textures/smoke_test.mjs +189 -0
- data/lib/three/animation/animation_action.rb +57 -0
- data/lib/three/animation/animation_clip.rb +22 -0
- data/lib/three/animation/animation_mixer.rb +43 -0
- data/lib/three/backends/base.rb +87 -0
- data/lib/three/backends/threejs/materialization.rb +143 -0
- data/lib/three/backends/threejs/parameters.rb +97 -0
- data/lib/three/backends/threejs/resource_management.rb +69 -0
- data/lib/three/backends/threejs/ruby_wasm_adapter.rb +873 -0
- data/lib/three/backends/threejs/synchronization.rb +224 -0
- data/lib/three/backends/threejs.rb +365 -0
- data/lib/three/cameras/camera.rb +39 -0
- data/lib/three/cameras/orthographic_camera.rb +107 -0
- data/lib/three/cameras/perspective_camera.rb +137 -0
- data/lib/three/constants.rb +40 -0
- data/lib/three/controls/orbit_controls.rb +118 -0
- data/lib/three/core/buffer_attribute.rb +151 -0
- data/lib/three/core/buffer_geometry.rb +181 -0
- data/lib/three/core/clock.rb +58 -0
- data/lib/three/core/event_dispatcher.rb +57 -0
- data/lib/three/core/layers.rb +75 -0
- data/lib/three/core/object3d.rb +331 -0
- data/lib/three/core/raycaster.rb +73 -0
- data/lib/three/dirty.rb +58 -0
- data/lib/three/exporters/three_json_exporter.rb +187 -0
- data/lib/three/geometries/box_geometry.rb +97 -0
- data/lib/three/geometries/plane_geometry.rb +70 -0
- data/lib/three/geometries/sphere_geometry.rb +107 -0
- data/lib/three/lights/ambient_light.rb +12 -0
- data/lib/three/lights/directional_light.rb +38 -0
- data/lib/three/lights/hemisphere_light.rb +34 -0
- data/lib/three/lights/light.rb +85 -0
- data/lib/three/lights/point_light.rb +33 -0
- data/lib/three/loaders/cube_texture_loader.rb +13 -0
- data/lib/three/loaders/gltf_loader.rb +48 -0
- data/lib/three/loaders/rgbe_loader.rb +15 -0
- data/lib/three/loaders/texture_loader.rb +13 -0
- data/lib/three/loaders/three_json_loader.rb +409 -0
- data/lib/three/materials/line_basic_material.rb +65 -0
- data/lib/three/materials/material.rb +158 -0
- data/lib/three/materials/mesh_basic_material.rb +64 -0
- data/lib/three/materials/mesh_lambert_material.rb +71 -0
- data/lib/three/materials/mesh_matcap_material.rb +86 -0
- data/lib/three/materials/mesh_normal_material.rb +42 -0
- data/lib/three/materials/mesh_phong_material.rb +119 -0
- data/lib/three/materials/mesh_physical_material.rb +155 -0
- data/lib/three/materials/mesh_standard_material.rb +149 -0
- data/lib/three/materials/mesh_toon_material.rb +98 -0
- data/lib/three/materials/points_material.rb +74 -0
- data/lib/three/materials/shadow_material.rb +45 -0
- data/lib/three/materials/sprite_material.rb +75 -0
- data/lib/three/math/color.rb +133 -0
- data/lib/three/math/euler.rb +197 -0
- data/lib/three/math/math_utils.rb +36 -0
- data/lib/three/math/matrix3.rb +255 -0
- data/lib/three/math/matrix4.rb +448 -0
- data/lib/three/math/quaternion.rb +277 -0
- data/lib/three/math/vector2.rb +95 -0
- data/lib/three/math/vector3.rb +396 -0
- data/lib/three/objects/external_object3d.rb +28 -0
- data/lib/three/objects/group.rb +12 -0
- data/lib/three/objects/instanced_mesh.rb +110 -0
- data/lib/three/objects/line.rb +41 -0
- data/lib/three/objects/mesh.rb +45 -0
- data/lib/three/objects/points.rb +41 -0
- data/lib/three/objects/sprite.rb +57 -0
- data/lib/three/postprocessing/dot_screen_pass.rb +83 -0
- data/lib/three/postprocessing/effect_composer.rb +56 -0
- data/lib/three/postprocessing/output_pass.rb +40 -0
- data/lib/three/postprocessing/render_pass.rb +42 -0
- data/lib/three/postprocessing/unreal_bloom_pass.rb +56 -0
- data/lib/three/renderers/renderer.rb +11 -0
- data/lib/three/renderers/threejs_renderer.rb +85 -0
- data/lib/three/scenes/scene.rb +29 -0
- data/lib/three/textures/cube_texture.rb +72 -0
- data/lib/three/textures/rgbe_texture.rb +45 -0
- data/lib/three/textures/texture.rb +200 -0
- data/lib/three/version.rb +5 -0
- data/lib/three-rb.rb +3 -0
- data/lib/three.rb +77 -0
- data/package.json +30 -0
- data/pnpm-lock.yaml +86 -0
- metadata +216 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b66b39cafbc0163bffb3b177eeaf1d397ac87fbed27046ca6f5673675fe001b9
|
|
4
|
+
data.tar.gz: 93dfc4ba66293d5090912b3082b2a84f87ba1d73d284606c9896d9a4b7f9d794
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 14776a59074de5a790244fc27c698988e7b98fb5c54abd7c8837368d8b029c1a5f3410814377aab663f466aa4e619228622590804d4b9fd261e9ced68877ce0d
|
|
7
|
+
data.tar.gz: 8292752e152f1aa24751e5b2b7468ca641c0beaaa36c17cfc8439466408214b7fca6fae65b3e0e8226c679586fd0aa532140b6d06fa22eda0205f7abbd57699a
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-05-15
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Ruby scene graph, math primitives, cameras, lights, geometries, textures, layers, raycasting helpers, and JSON export/load.
|
|
8
|
+
- Mesh, instanced mesh, line, points, and sprite object support.
|
|
9
|
+
- Common material APIs including basic, Lambert, Phong, standard, physical, matcap, toon, normal, shadow, line, points, and sprite materials.
|
|
10
|
+
- Browser rendering through ruby.wasm and a delegated three.js backend.
|
|
11
|
+
- Browser examples and Playwright smoke tests for cube, composition, textures, cubemap, glTF/DRACO, serialization, picking, primitives, and postprocessing.
|
|
12
|
+
- Texture loading, cube textures, RGBE environment textures, glTF loading, DRACO decoder configuration, animation mixers, OrbitControls, instancing, picking, shadows, and loaded-asset traversal/disposal helpers.
|
|
13
|
+
- Initial postprocessing wrappers for `EffectComposer`, `RenderPass`, `UnrealBloomPass`, `DotScreenPass`, and `OutputPass`.
|
|
14
|
+
- Deterministic JSON fixture regression coverage for exporter/loader compatibility.
|
|
15
|
+
- Release install smoke and preflight tasks for validating the built gem outside the repository load path.
|
|
16
|
+
|
|
17
|
+
### Notes
|
|
18
|
+
|
|
19
|
+
- The first release is browser-first alpha quality. Native rendering, full three.js compatibility, broad addon coverage, WebGPU, and XR are intentionally outside the initial public scope.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LEF
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# three-rb
|
|
2
|
+
|
|
3
|
+
Ruby 3D Library.
|
|
4
|
+
|
|
5
|
+
Published to RubyGems as `three-rb`; require it in Ruby as `three`.
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
This project is in browser-first alpha. The current code covers the gem foundation, math primitives, scene graph basics, geometry/material objects, dirty-tracked backend sync, JSON export/load, browser examples, and a three.js backend/renderer bridge through ruby.wasm.
|
|
10
|
+
|
|
11
|
+
## Browser-first alpha scope
|
|
12
|
+
|
|
13
|
+
Supported scope for the first public release:
|
|
14
|
+
|
|
15
|
+
- Pure Ruby scene construction, math, cameras, lights, geometry, materials, textures, layers, raycasting helpers, and JSON export/load.
|
|
16
|
+
- Browser rendering through `Three::Renderers::ThreeJSRenderer`, ruby.wasm, and pnpm-managed `three@0.184.0`.
|
|
17
|
+
- JavaScript-delegated browser features for texture loading, cube/RGBE textures, glTF/DRACO loading, OrbitControls, animation mixers, instancing, picking, shadows, and an initial postprocessing pipeline.
|
|
18
|
+
|
|
19
|
+
Out of scope for the first public release:
|
|
20
|
+
|
|
21
|
+
- A Ruby-native OpenGL/Vulkan/software renderer.
|
|
22
|
+
- Full three.js API compatibility.
|
|
23
|
+
- Stable APIs for every addon loader, render target, postprocessing pass, WebGPU, or XR workflow.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
After a release is published:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
gem install three-rb
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or add it to a Gemfile:
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
gem "three-rb", "~> 0.1"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
require "three"
|
|
43
|
+
|
|
44
|
+
scene = Three::Scene.new
|
|
45
|
+
camera = Three::PerspectiveCamera.new(75, aspect: 16.0 / 9.0)
|
|
46
|
+
camera.position.z = 5
|
|
47
|
+
|
|
48
|
+
geometry = Three::BoxGeometry.new(1, 1, 1)
|
|
49
|
+
material = Three::MeshBasicMaterial.new(color: 0x00ff00)
|
|
50
|
+
cube = Three::Mesh.new(geometry, material)
|
|
51
|
+
|
|
52
|
+
scene.add(cube)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Browser rendering is available through `Three::Renderers::ThreeJSRenderer`, which targets three.js from ruby.wasm.
|
|
56
|
+
|
|
57
|
+
## Browser Example
|
|
58
|
+
|
|
59
|
+
Install browser dependencies, serve the repository root, and open one of the browser examples:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
pnpm install
|
|
63
|
+
ruby -run -e httpd . -p 8000
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
http://localhost:8000/examples/browser/cube/
|
|
68
|
+
http://localhost:8000/examples/browser/composition/
|
|
69
|
+
http://localhost:8000/examples/browser/textures/
|
|
70
|
+
http://localhost:8000/examples/browser/cubemap/
|
|
71
|
+
http://localhost:8000/examples/browser/gltf/
|
|
72
|
+
http://localhost:8000/examples/browser/serialization/
|
|
73
|
+
http://localhost:8000/examples/browser/picking/
|
|
74
|
+
http://localhost:8000/examples/browser/primitives/
|
|
75
|
+
http://localhost:8000/examples/browser/postprocessing/
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
See [Browser Examples](examples/browser/README.md) for the feature coverage map and per-example smoke commands. See [Browser Runtime](docs/browser-runtime.md) for the current embedding and boot contract.
|
|
79
|
+
|
|
80
|
+
The examples load pnpm-managed browser packages from `node_modules/`: `@ruby/3.4-wasm-wasi@2.9.4-2026-05-11-a`, `@ruby/wasm-wasi@2.9.4-2026-05-11-a`, and `three@0.184.0`.
|
|
81
|
+
|
|
82
|
+
Run the optional browser smoke tests:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
pnpm install
|
|
86
|
+
pnpm exec playwright install chromium
|
|
87
|
+
pnpm test:browser
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Run the optional browser sync benchmarks:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
pnpm benchmark:browser
|
|
94
|
+
pnpm benchmark:browser:mesh-sync
|
|
95
|
+
pnpm benchmark:browser:instanced-mesh-sync
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
Install dependencies:
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
bundle install
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Run tests:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
bundle exec rake test
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Build and install the gem into a temporary `GEM_HOME`, then run the install smoke test:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
bundle exec rake release:gem_smoke
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Export a Ruby-authored scene to a deterministic JSON-friendly hash:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
exported = Three::Exporters::ThreeJSONExporter.new.export(scene)
|
|
122
|
+
fixture = Three::Exporters::ThreeJSONExporter.new(deterministic_ids: true).export(scene)
|
|
123
|
+
json = scene.to_json
|
|
124
|
+
loaded_scene = Three::Loaders::ThreeJSONLoader.new.parse(json)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Run the local release preflight check:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
pnpm install
|
|
131
|
+
pnpm exec playwright install chromium
|
|
132
|
+
bundle exec rake release:preflight
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Run the full local CI-equivalent check, including dependency audits:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
pnpm install --frozen-lockfile --ignore-scripts
|
|
139
|
+
pnpm audit --audit-level moderate
|
|
140
|
+
pnpm audit signatures
|
|
141
|
+
pnpm exec playwright install chromium
|
|
142
|
+
bundle exec rake release:preflight
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Documents
|
|
146
|
+
|
|
147
|
+
- [Implementation Plan](docs/implementation-plan.md)
|
|
148
|
+
- [Next Work](docs/next-work.md)
|
|
149
|
+
- [Browser Runtime](docs/browser-runtime.md)
|
|
150
|
+
- [Browser Examples](examples/browser/README.md)
|
|
151
|
+
- [Loaded Asset Traversal and Disposal Design](docs/loaded-assets-design.md)
|
|
152
|
+
- [Release Readiness](docs/release-readiness.md)
|
|
153
|
+
- [Publishing](docs/publishing.md)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Browser Runtime
|
|
2
|
+
|
|
3
|
+
This guide describes the current browser runtime shape for embedding three-rb outside the repository examples. The browser runtime is still browser-first alpha: Ruby builds the scene graph, ruby.wasm runs the Ruby code, and pnpm-managed three.js modules do the actual WebGL rendering.
|
|
4
|
+
|
|
5
|
+
For the example coverage map and per-example smoke commands, see `examples/browser/README.md`.
|
|
6
|
+
|
|
7
|
+
## Runtime Shape
|
|
8
|
+
|
|
9
|
+
A browser page using three-rb needs four pieces:
|
|
10
|
+
|
|
11
|
+
1. An HTTP-served page with a canvas element.
|
|
12
|
+
2. An import map or bundler setup that resolves ruby.wasm, three.js, and three.js addon modules.
|
|
13
|
+
3. A JavaScript boot module that exposes the required three.js constructors to Ruby and starts ruby.wasm.
|
|
14
|
+
4. A Ruby entrypoint that waits for three.js, requires `three`, creates a scene, and renders through `Three::Renderers::ThreeJSRenderer`.
|
|
15
|
+
|
|
16
|
+
Do not use `file://` for browser runs. The examples assume an HTTP server because browser module loading, wasm loading, and asset loading all need stable URL resolution.
|
|
17
|
+
|
|
18
|
+
## Browser Dependencies
|
|
19
|
+
|
|
20
|
+
The runtime currently follows the pinned versions in `package.json`:
|
|
21
|
+
|
|
22
|
+
- `@bjorn3/browser_wasi_shim@0.4.2`
|
|
23
|
+
- `@ruby/3.4-wasm-wasi@2.9.4-2026-05-11-a`
|
|
24
|
+
- `@ruby/wasm-wasi@2.9.4-2026-05-11-a`
|
|
25
|
+
- `three@0.184.0`
|
|
26
|
+
|
|
27
|
+
Install them from the repository root with:
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
pnpm install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Keep these pins synchronized with browser smoke coverage. The public Ruby API and the JavaScript delegated backend are coupled closely enough that dependency drift should go through `pnpm test:browser` before release work.
|
|
34
|
+
|
|
35
|
+
## HTML Requirements
|
|
36
|
+
|
|
37
|
+
The page needs a canvas that Ruby can select:
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<canvas id="scene"></canvas>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
When using import maps like the examples, the page also needs mappings for ruby.wasm, three.js, and three.js addons:
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<script type="importmap">
|
|
47
|
+
{
|
|
48
|
+
"imports": {
|
|
49
|
+
"@bjorn3/browser_wasi_shim": "/node_modules/@bjorn3/browser_wasi_shim/dist/index.js",
|
|
50
|
+
"@ruby/wasm-wasi/browser": "/node_modules/@ruby/wasm-wasi/dist/esm/browser.js",
|
|
51
|
+
"three": "/node_modules/three/build/three.module.js",
|
|
52
|
+
"three/addons/": "/node_modules/three/examples/jsm/"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
</script>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Applications can use a bundler instead of an import map, but the same modules and addon paths must be available to the JavaScript boot module.
|
|
59
|
+
|
|
60
|
+
## JavaScript Boot Contract
|
|
61
|
+
|
|
62
|
+
Use `examples/browser/shared/boot.mjs` as the reference implementation. Example-local boot files are intentionally small; they pass the Ruby entrypoint and clear color into the shared boot helper.
|
|
63
|
+
|
|
64
|
+
The boot module is responsible for:
|
|
65
|
+
|
|
66
|
+
- Importing `DefaultRubyVM` from `@ruby/wasm-wasi/browser`.
|
|
67
|
+
- Importing `three` and any addon constructors used by Ruby.
|
|
68
|
+
- Assigning `globalThis.THREE` before Ruby creates `Three::Renderers::ThreeJSRenderer`.
|
|
69
|
+
- Assigning addon constructors before Ruby calls addon wrappers:
|
|
70
|
+
- `globalThis.THREE_GLTF_LOADER`
|
|
71
|
+
- `globalThis.THREE_DRACO_LOADER`
|
|
72
|
+
- `globalThis.THREE_RGBE_LOADER`
|
|
73
|
+
- `globalThis.THREE_ORBIT_CONTROLS`
|
|
74
|
+
- `globalThis.THREE_EFFECT_COMPOSER`
|
|
75
|
+
- `globalThis.THREE_RENDER_PASS`
|
|
76
|
+
- `globalThis.THREE_UNREAL_BLOOM_PASS`
|
|
77
|
+
- `globalThis.THREE_DOT_SCREEN_PASS`
|
|
78
|
+
- `globalThis.THREE_OUTPUT_PASS`
|
|
79
|
+
- Setting `globalThis.__threeReady` to a promise Ruby can wait on.
|
|
80
|
+
- Loading `/node_modules/@ruby/3.4-wasm-wasi/dist/ruby+stdlib.wasm`.
|
|
81
|
+
- Starting the Ruby VM and loading the Ruby entrypoint through `JS::RequireRemote`.
|
|
82
|
+
|
|
83
|
+
The shared helper also installs optional render helpers used by smoke tests to draw immediately from Ruby renderer calls and expose render counters for deterministic assertions. Custom applications can keep that behavior or call directly into three.js through the renderer backend fallback.
|
|
84
|
+
|
|
85
|
+
Write a custom boot module when the application has different asset paths, a bundler output path, a smaller addon set, a custom status/error UI, or a deployment layout that does not match the repository root. Keep the same global constructor contract unless the Ruby backend gains a different injection API.
|
|
86
|
+
|
|
87
|
+
## Ruby Entrypoint
|
|
88
|
+
|
|
89
|
+
The Ruby side should wait for the JavaScript boot module, require the library, create a scene, and attach the renderer to the existing canvas:
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
require "js"
|
|
93
|
+
|
|
94
|
+
JS.global[:__threeReady].await
|
|
95
|
+
|
|
96
|
+
require_relative "../../../lib/three"
|
|
97
|
+
|
|
98
|
+
scene = Three::Scene.new
|
|
99
|
+
camera = Three::PerspectiveCamera.new(70, aspect: 1.0, near: 0.1, far: 100)
|
|
100
|
+
camera.position.z = 3
|
|
101
|
+
|
|
102
|
+
mesh = Three::Mesh.new(
|
|
103
|
+
Three::BoxGeometry.new(1, 1, 1),
|
|
104
|
+
Three::MeshBasicMaterial.new(color: 0x4ed08f)
|
|
105
|
+
)
|
|
106
|
+
scene.add(mesh)
|
|
107
|
+
|
|
108
|
+
renderer = Three::Renderers::ThreeJSRenderer.new(
|
|
109
|
+
canvas: "#scene",
|
|
110
|
+
antialias: true,
|
|
111
|
+
alpha: false
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
renderer.set_size(640, 480)
|
|
115
|
+
renderer.render(scene, camera)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`canvas:` may be a CSS selector string or a JavaScript canvas object. Selector strings are resolved with `document.querySelector`.
|
|
119
|
+
|
|
120
|
+
For responsive layouts, follow the browser examples: read the containing element's client width and height, update the camera aspect/projection matrix, call `renderer.set_size(width, height)`, and listen for `resize`.
|
|
121
|
+
|
|
122
|
+
For animation, call `renderer.animation_loop`:
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
renderer.animation_loop do
|
|
126
|
+
mesh.rotation.x += 0.01
|
|
127
|
+
mesh.rotation.y += 0.015
|
|
128
|
+
renderer.render(scene, camera)
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For postprocessing, render through `composer.render(scene, camera)` instead of `renderer.render(scene, camera)` after configuring `Three::Postprocessing::EffectComposer` and its passes.
|
|
133
|
+
|
|
134
|
+
## Current Limits
|
|
135
|
+
|
|
136
|
+
The browser runtime intentionally does not promise full three.js compatibility yet.
|
|
137
|
+
|
|
138
|
+
- There is no Ruby-native OpenGL, Vulkan, WebGPU, or software renderer.
|
|
139
|
+
- Rendering is delegated to three.js through ruby.wasm.
|
|
140
|
+
- Addon wrappers only work when their JavaScript constructors are registered on `globalThis`.
|
|
141
|
+
- The first public scope does not include stable APIs for every loader, material, render target, postprocessing pass, WebGPU, or XR workflow.
|
|
142
|
+
- `examples/browser/shared/boot.mjs` is a reference implementation for this repository's examples, not a separate stable package.
|
|
143
|
+
- `preserveDrawingBuffer: true` is useful for deterministic canvas smoke tests, but applications do not need it by default.
|
|
144
|
+
|
|
145
|
+
## Verification
|
|
146
|
+
|
|
147
|
+
Use the browser examples as executable documentation:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
pnpm test:browser
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Before release work, run the release gates documented in `docs/release-readiness.md` and the publishing checklist in `docs/publishing.md`. Browser boot changes should go through `bundle exec rake release:preflight` because that includes the Ruby tests, gem install smoke, and browser smoke tests.
|