three-rb 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -1
- data/README.md +66 -3
- data/docs/browser-runtime.md +92 -24
- data/docs/loaded-assets-design.md +1 -1
- data/docs/next-work.md +9 -5
- data/docs/publishing.md +119 -23
- data/docs/release-readiness.md +5 -3
- data/docs/standalone-browser-app.md +106 -0
- data/examples/browser/README.md +8 -0
- data/examples/browser/composition/main.rb +44 -64
- data/examples/browser/cube/main.rb +4 -34
- data/examples/browser/cubemap/assets/checker.svg +11 -0
- data/examples/browser/cubemap/main.rb +17 -40
- data/examples/browser/gltf/main.rb +30 -50
- data/examples/browser/picking/main.rb +27 -53
- data/examples/browser/postprocessing/main.rb +23 -42
- data/examples/browser/primitives/assets/checker.svg +11 -0
- data/examples/browser/primitives/main.rb +19 -42
- data/examples/browser/ruby/README.md +24 -0
- data/examples/browser/ruby/boot.mjs +6 -0
- data/examples/browser/ruby/index.html +142 -0
- data/examples/browser/ruby/main.rb +313 -0
- data/examples/browser/ruby/smoke_test.mjs +126 -0
- data/examples/browser/serialization/assets/checker.svg +11 -0
- data/examples/browser/serialization/main.rb +20 -42
- data/examples/browser/shared/boot.mjs +37 -5
- data/examples/browser/textures/assets/checker.svg +11 -0
- data/examples/browser/textures/assets/studio.hdr +5 -0
- data/examples/browser/textures/main.rb +23 -41
- data/exe/three-rb +56 -0
- data/lib/three/backends/threejs/materialization.rb +6 -0
- data/lib/three/backends/threejs/parameters.rb +17 -0
- data/lib/three/backends/threejs/ruby_wasm_adapter.rb +166 -59
- data/lib/three/backends/threejs/synchronization.rb +38 -4
- data/lib/three/backends/threejs.rb +24 -0
- data/lib/three/browser.rb +389 -0
- data/lib/three/constants.rb +6 -0
- data/lib/three/core/buffer_attribute.rb +5 -1
- data/lib/three/core/buffer_geometry.rb +29 -1
- data/lib/three/core/object3d.rb +39 -1
- data/lib/three/exporters/three_json_exporter.rb +3 -0
- data/lib/three/generators/browser_example.rb +396 -0
- data/lib/three/geometries/text_geometry.rb +41 -0
- data/lib/three/loaders/font_loader.rb +29 -0
- data/lib/three/loaders/three_json_loader.rb +92 -46
- data/lib/three/materials/material.rb +2 -1
- data/lib/three/math/matrix4.rb +27 -0
- data/lib/three/renderers/threejs_renderer.rb +19 -0
- data/lib/three/scenes/fog.rb +86 -0
- data/lib/three/scenes/scene.rb +19 -1
- data/lib/three/textures/texture.rb +2 -1
- data/lib/three/version.rb +1 -1
- data/lib/three.rb +4 -0
- data/package.json +2 -1
- metadata +26 -8
- /data/examples/browser/{assets → composition/assets}/checker.svg +0 -0
- /data/examples/browser/{assets → gltf/assets}/animated_triangle.gltf +0 -0
- /data/examples/browser/{assets → gltf/assets}/compressed_triangle.gltf +0 -0
- /data/examples/browser/{assets → gltf/assets}/triangle.gltf +0 -0
- /data/examples/browser/{assets → ruby/assets}/studio.hdr +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b6b3331ebb395126e0bbd0003e8cb8e9da2648107319e4c0953e6a1d33ddbfd
|
|
4
|
+
data.tar.gz: 1867f60db80fc386322c82ebc35b5bbda234712f2b9370164487e0105066001c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ee90d10b58348b809c087d7c25dc29dd62c4173e83892bfe09710002c83dac9ccd65c8aaa1af91538100d262d595278904267273f1a0d4baa75ed2fe4dca6c45
|
|
7
|
+
data.tar.gz: f65cf3c1132a728e54601ca7b4f0de2433755320b1d9d842844118606e4391c4d286be65386c2d1a548132b406759e7d6af45be2fe604fad08034f1e9a50759a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.1 - 2026-05-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added a generated Ruby browser example template that copies the full gemstone example, including its local HDR asset.
|
|
8
|
+
- Added generator coverage for Ruby example asset copying and Ruby-only browser entrypoints.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Moved browser example assets into example-local asset directories so generated examples and smoke tests use self-contained paths.
|
|
13
|
+
- Strengthened release readiness checks for the browser generator template and installed executable.
|
|
14
|
+
|
|
15
|
+
## 0.2.0 - 2026-05-17
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Expanded `Three::Browser` helpers so browser examples can stay in Ruby without direct application-level `require "js"` or `JS.global` usage.
|
|
20
|
+
- Added the `three-rb browser` generator for creating standalone browser apps with Ruby-only entrypoints.
|
|
21
|
+
- Added a Ruby gemstone browser example with deterministic smoke coverage.
|
|
22
|
+
- Added scene fog and override material support.
|
|
23
|
+
- Added manual `Object3D` matrix support.
|
|
24
|
+
- Added text geometry and font loader APIs.
|
|
25
|
+
- Added JSON resource metadata preservation for exported and loaded scenes.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Converted browser examples to the Ruby browser helper API and shared browser boot path.
|
|
30
|
+
- Improved browser addon error messages with more actionable guidance.
|
|
31
|
+
- Strengthened release checks for installed gem behavior, the installed executable, and generated browser apps.
|
|
32
|
+
- Expanded browser runtime and standalone app documentation.
|
|
33
|
+
|
|
3
34
|
## 0.1.0 - 2026-05-15
|
|
4
35
|
|
|
5
36
|
### Added
|
|
@@ -8,11 +39,12 @@
|
|
|
8
39
|
- Mesh, instanced mesh, line, points, and sprite object support.
|
|
9
40
|
- Common material APIs including basic, Lambert, Phong, standard, physical, matcap, toon, normal, shadow, line, points, and sprite materials.
|
|
10
41
|
- Browser rendering through ruby.wasm and a delegated three.js backend.
|
|
42
|
+
- `Three::Browser` helpers and a `three-rb browser` generator for Ruby-only browser entrypoints that avoid application-level `require "js"` and `JS.global` calls.
|
|
11
43
|
- Browser examples and Playwright smoke tests for cube, composition, textures, cubemap, glTF/DRACO, serialization, picking, primitives, and postprocessing.
|
|
12
44
|
- 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
45
|
- Initial postprocessing wrappers for `EffectComposer`, `RenderPass`, `UnrealBloomPass`, `DotScreenPass`, and `OutputPass`.
|
|
14
46
|
- 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.
|
|
47
|
+
- Release install smoke and preflight tasks for validating the built gem, installed executable, and generated browser app outside the repository load path.
|
|
16
48
|
|
|
17
49
|
### Notes
|
|
18
50
|
|
data/README.md
CHANGED
|
@@ -24,7 +24,7 @@ Out of scope for the first public release:
|
|
|
24
24
|
|
|
25
25
|
## Installation
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Install the released gem from RubyGems:
|
|
28
28
|
|
|
29
29
|
```sh
|
|
30
30
|
gem install three-rb
|
|
@@ -36,11 +36,41 @@ Or add it to a Gemfile:
|
|
|
36
36
|
gem "three-rb", "~> 0.1"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
Browser rendering examples also need `pnpm`, because ruby.wasm, three.js, and three.js addons are installed from `package.json`.
|
|
40
|
+
|
|
39
41
|
## Quick Start
|
|
40
42
|
|
|
43
|
+
three-rb is browser-first. The fastest way to try the released gem is to unpack a writable copy of the gem and run one of the included browser examples:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
gem install three-rb
|
|
47
|
+
mkdir hello-three-rb
|
|
48
|
+
cd hello-three-rb
|
|
49
|
+
gem unpack three-rb
|
|
50
|
+
cd three-rb-*/
|
|
51
|
+
pnpm install
|
|
52
|
+
ruby -run -e httpd . -p 8000
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If Ruby reports that `webrick` is not found, install it once with `gem install webrick`. Ruby 3.0 and later no longer include WEBrick as a standard library.
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
http://localhost:8000/examples/browser/ruby/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This page runs the Ruby entrypoint at `examples/browser/ruby/main.rb` through ruby.wasm and renders a transparent red gemstone and extruded `three-rb` title with three.js. Use `http://localhost:8000/...`; do not open the files with `file://`, because the browser runtime loads ES modules, wasm, and assets over HTTP.
|
|
62
|
+
|
|
63
|
+
After the ruby example works, inspect `examples/browser/ruby/main.rb` to see the Ruby scene code. For the smallest possible browser scene, see `examples/browser/cube/main.rb`. For a standalone app directory with your own Ruby entrypoint, see [Standalone Browser App](docs/standalone-browser-app.md).
|
|
64
|
+
|
|
65
|
+
## Plain Ruby Check
|
|
66
|
+
|
|
67
|
+
If you only want to confirm the Ruby API loads without browser rendering, create `hello_three.rb`:
|
|
68
|
+
|
|
41
69
|
```ruby
|
|
42
70
|
require "three"
|
|
43
71
|
|
|
72
|
+
puts "three-rb #{Three::VERSION}"
|
|
73
|
+
|
|
44
74
|
scene = Three::Scene.new
|
|
45
75
|
camera = Three::PerspectiveCamera.new(75, aspect: 16.0 / 9.0)
|
|
46
76
|
camera.position.z = 5
|
|
@@ -50,20 +80,40 @@ material = Three::MeshBasicMaterial.new(color: 0x00ff00)
|
|
|
50
80
|
cube = Three::Mesh.new(geometry, material)
|
|
51
81
|
|
|
52
82
|
scene.add(cube)
|
|
83
|
+
|
|
84
|
+
puts scene.class
|
|
85
|
+
puts cube.class
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Run it:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
ruby hello_three.rb
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
You should see the library load and create Ruby scene objects:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
three-rb 0.1.0
|
|
98
|
+
Three::Scene
|
|
99
|
+
Three::Mesh
|
|
53
100
|
```
|
|
54
101
|
|
|
55
102
|
Browser rendering is available through `Three::Renderers::ThreeJSRenderer`, which targets three.js from ruby.wasm.
|
|
56
103
|
|
|
57
|
-
## Browser
|
|
104
|
+
## Browser Examples In This Repository
|
|
58
105
|
|
|
59
|
-
|
|
106
|
+
When developing this repository, install browser dependencies, serve the repository root, and open one of the browser examples:
|
|
60
107
|
|
|
61
108
|
```sh
|
|
62
109
|
pnpm install
|
|
63
110
|
ruby -run -e httpd . -p 8000
|
|
64
111
|
```
|
|
65
112
|
|
|
113
|
+
If `ruby -run -e httpd` reports that `webrick` is not found, run `gem install webrick` and retry. Ruby 3.0 and later require WEBrick to be installed separately.
|
|
114
|
+
|
|
66
115
|
```text
|
|
116
|
+
http://localhost:8000/examples/browser/ruby/
|
|
67
117
|
http://localhost:8000/examples/browser/cube/
|
|
68
118
|
http://localhost:8000/examples/browser/composition/
|
|
69
119
|
http://localhost:8000/examples/browser/textures/
|
|
@@ -79,6 +129,18 @@ See [Browser Examples](examples/browser/README.md) for the feature coverage map
|
|
|
79
129
|
|
|
80
130
|
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
131
|
|
|
132
|
+
To start a standalone browser app from the installed gem:
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
three-rb browser examples/browser/quickstart
|
|
136
|
+
pnpm install
|
|
137
|
+
ruby -run -e httpd . -p 8000
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Use `three-rb browser examples/browser/ruby` instead when you want the richer Ruby gemstone sample with its assets kept under `examples/browser/ruby/assets/`.
|
|
141
|
+
|
|
142
|
+
The generated Ruby entrypoint uses `Three::Browser.run`, so ordinary scene code does not need `require "js"` or `JS.global`.
|
|
143
|
+
|
|
82
144
|
Run the optional browser smoke tests:
|
|
83
145
|
|
|
84
146
|
```sh
|
|
@@ -148,6 +210,7 @@ bundle exec rake release:preflight
|
|
|
148
210
|
- [Next Work](docs/next-work.md)
|
|
149
211
|
- [Browser Runtime](docs/browser-runtime.md)
|
|
150
212
|
- [Browser Examples](examples/browser/README.md)
|
|
213
|
+
- [Standalone Browser App](docs/standalone-browser-app.md)
|
|
151
214
|
- [Loaded Asset Traversal and Disposal Design](docs/loaded-assets-design.md)
|
|
152
215
|
- [Release Readiness](docs/release-readiness.md)
|
|
153
216
|
- [Publishing](docs/publishing.md)
|
data/docs/browser-runtime.md
CHANGED
|
@@ -11,7 +11,7 @@ A browser page using three-rb needs four pieces:
|
|
|
11
11
|
1. An HTTP-served page with a canvas element.
|
|
12
12
|
2. An import map or bundler setup that resolves ruby.wasm, three.js, and three.js addon modules.
|
|
13
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
|
|
14
|
+
4. A Ruby entrypoint that requires `three`, creates a scene inside `Three::Browser.run`, and renders through `Three::Renderers::ThreeJSRenderer`.
|
|
15
15
|
|
|
16
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
17
|
|
|
@@ -84,45 +84,45 @@ The shared helper also installs optional render helpers used by smoke tests to d
|
|
|
84
84
|
|
|
85
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
86
|
|
|
87
|
+
If a Ruby wrapper needs an addon constructor that the boot module did not register, three-rb raises an error naming the missing `globalThis.THREE_*` value and the import/assignment lines to add to `boot.mjs`.
|
|
88
|
+
|
|
87
89
|
## Ruby Entrypoint
|
|
88
90
|
|
|
89
|
-
The Ruby side should
|
|
91
|
+
The Ruby side should require the library, create a scene inside `Three::Browser.run`, and attach the renderer to the existing canvas. `Three::Browser.run` waits for the JavaScript boot module and handles the example status/error UI, so application scene code does not need to call `JS.global` directly:
|
|
90
92
|
|
|
91
93
|
```ruby
|
|
92
|
-
require "js"
|
|
93
|
-
|
|
94
|
-
JS.global[:__threeReady].await
|
|
95
|
-
|
|
96
94
|
require_relative "../../../lib/three"
|
|
97
95
|
|
|
98
|
-
scene
|
|
99
|
-
|
|
100
|
-
camera.
|
|
96
|
+
Three::Browser.run(starting: "Starting Ruby scene") do |app|
|
|
97
|
+
scene = Three::Scene.new
|
|
98
|
+
camera = Three::PerspectiveCamera.new(70, aspect: 1.0, near: 0.1, far: 100)
|
|
99
|
+
camera.position.z = 3
|
|
101
100
|
|
|
102
|
-
mesh = Three::Mesh.new(
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
-
scene.add(mesh)
|
|
101
|
+
mesh = Three::Mesh.new(
|
|
102
|
+
Three::BoxGeometry.new(1, 1, 1),
|
|
103
|
+
Three::MeshBasicMaterial.new(color: 0x4ed08f)
|
|
104
|
+
)
|
|
105
|
+
scene.add(mesh)
|
|
107
106
|
|
|
108
|
-
renderer = Three::Renderers::ThreeJSRenderer.new(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
)
|
|
107
|
+
renderer = Three::Renderers::ThreeJSRenderer.new(
|
|
108
|
+
canvas: "#scene",
|
|
109
|
+
antialias: true,
|
|
110
|
+
alpha: false
|
|
111
|
+
)
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
renderer.render(scene, camera)
|
|
113
|
+
app.resize_renderer(renderer, camera)
|
|
114
|
+
renderer.render(scene, camera)
|
|
115
|
+
end
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
`canvas:` may be a CSS selector string or a JavaScript canvas object. Selector strings are resolved with `document.querySelector`.
|
|
119
119
|
|
|
120
|
-
For responsive layouts,
|
|
120
|
+
For responsive layouts, use `app.resize_renderer(renderer, camera)` for perspective cameras. For custom orthographic sizing, pass a block and update the camera before the helper sets the renderer size.
|
|
121
121
|
|
|
122
|
-
For animation,
|
|
122
|
+
For animation, prefer `app.animation_loop(renderer)`. It delegates to the renderer's browser animation loop and keeps the entrypoint on the `Three::Browser` API surface:
|
|
123
123
|
|
|
124
124
|
```ruby
|
|
125
|
-
|
|
125
|
+
app.animation_loop(renderer) do
|
|
126
126
|
mesh.rotation.x += 0.01
|
|
127
127
|
mesh.rotation.y += 0.015
|
|
128
128
|
renderer.render(scene, camera)
|
|
@@ -131,6 +131,73 @@ end
|
|
|
131
131
|
|
|
132
132
|
For postprocessing, render through `composer.render(scene, camera)` instead of `renderer.render(scene, camera)` after configuring `Three::Postprocessing::EffectComposer` and its passes.
|
|
133
133
|
|
|
134
|
+
## Three::Browser API
|
|
135
|
+
|
|
136
|
+
`Three::Browser` is the public convenience layer for browser entrypoints. It keeps ordinary scene code Ruby-only while the JavaScript boot module handles ruby.wasm and ES module setup. Treat these methods as the first-choice browser API before reaching for direct JS bridge calls.
|
|
137
|
+
|
|
138
|
+
Lifecycle and sizing:
|
|
139
|
+
|
|
140
|
+
- `Three::Browser.run(starting: "...") { |app| ... }` waits for the boot module, creates an application helper, updates the status UI, and reports boot failures.
|
|
141
|
+
- `app.resize_renderer(renderer, camera)` reads the default `#viewport`, updates a perspective camera's aspect/projection matrix, calls `renderer.set_size`, and registers a resize listener.
|
|
142
|
+
- `app.resize_renderer(renderer, camera) { |width, height, aspect| ... }` supports custom camera sizing such as orthographic views.
|
|
143
|
+
- `app.on_resize { |width, height, aspect| ... }` registers a lower-level resize callback and runs it once immediately.
|
|
144
|
+
- `app.animation_loop(renderer) { ... }` delegates to `renderer.animation_loop`.
|
|
145
|
+
- `app.animation_loop { |time| ... }` uses `requestAnimationFrame` directly when a renderer loop is not appropriate.
|
|
146
|
+
|
|
147
|
+
DOM and events:
|
|
148
|
+
|
|
149
|
+
- `app.element(renderer.dom_element)` wraps a browser element for event handling and pointer coordinate helpers.
|
|
150
|
+
- `element.on("click") { |event| ... }` registers a DOM event without exposing `JS.global`.
|
|
151
|
+
- `element.pointer_ndc(event)` converts pointer events to normalized device coordinates for `Raycaster#set_from_camera`.
|
|
152
|
+
- `app.pointer_ndc(event, target: "#viewport")` performs the same conversion against a selector, raw element, or `Three::Browser::Element`.
|
|
153
|
+
- `app.on_pointer("click", target: renderer.dom_element) { |event, x, y| ... }` registers a pointer event and yields normalized device coordinates.
|
|
154
|
+
- `app.on_key("keydown", key: "Escape") { |event| ... }` registers keyboard events on `window` by default. Omit `key:` to receive every event.
|
|
155
|
+
|
|
156
|
+
State and diagnostics:
|
|
157
|
+
|
|
158
|
+
- `app.storage` wraps `localStorage`; `app.storage(:session)` wraps `sessionStorage`.
|
|
159
|
+
- `storage.set(:name, value)`, `storage.get(:name)`, `storage.delete(:name)`, `storage.clear`, `storage.length`, and `storage.key(index)` cover simple browser storage access.
|
|
160
|
+
- `app.expose(...)`, `app.set`, `app.get`, and `app.increment` are intended for diagnostics, smoke tests, and small browser-visible state values.
|
|
161
|
+
|
|
162
|
+
Escape hatch:
|
|
163
|
+
|
|
164
|
+
- `Three::Browser.js` returns `JS.global` and is the explicit escape hatch for advanced browser integrations that three-rb does not wrap yet. Keep usage isolated and prefer adding a Ruby helper when the pattern is reusable.
|
|
165
|
+
|
|
166
|
+
Example pointer picking:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
pointer = Three::Vector2.new
|
|
170
|
+
raycaster = Three::Raycaster.new(backend: renderer.backend)
|
|
171
|
+
|
|
172
|
+
app.on_pointer("click", target: renderer.dom_element) do |_event, x, y|
|
|
173
|
+
pointer.set(x, y)
|
|
174
|
+
raycaster.set_from_camera(pointer, camera)
|
|
175
|
+
end
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Generator
|
|
179
|
+
|
|
180
|
+
For standalone projects, install the gem and generate a Ruby-only browser example:
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
three-rb browser examples/browser/quickstart
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`quickstart` generates an asset-free rotating cube. Use `three-rb browser examples/browser/ruby` to generate the richer Ruby gemstone sample; its HDR asset is copied under `examples/browser/ruby/assets/`.
|
|
187
|
+
|
|
188
|
+
The generator copies the browser runtime files, `package.json`, `pnpm-lock.yaml`, and `lib/` into the served project root, then creates `index.html`, `boot.mjs`, `main.rb`, and `README.md` for the example. Templates that need local files keep them under the generated example's `assets/` directory.
|
|
189
|
+
|
|
190
|
+
## JavaScript Escape Hatch
|
|
191
|
+
|
|
192
|
+
Most browser scene code should not need `require "js"` or `JS.global`. JavaScript is still the right layer for:
|
|
193
|
+
|
|
194
|
+
- The boot module that imports ES modules and starts ruby.wasm.
|
|
195
|
+
- Custom HTML UI outside the helpers in `Three::Browser`.
|
|
196
|
+
- Browser APIs that three-rb does not wrap yet, such as WebSocket, drag/drop, pointer lock, fullscreen, WebXR session setup, or application-specific JavaScript callbacks.
|
|
197
|
+
- three.js addons that do not yet have Ruby wrappers.
|
|
198
|
+
|
|
199
|
+
When a feature needs direct JavaScript access, prefer adding a small Ruby wrapper or `Three::Browser` helper first. Use `Three::Browser.js` as the explicit escape hatch for application-specific integrations, and keep it isolated from scene construction code.
|
|
200
|
+
|
|
134
201
|
## Current Limits
|
|
135
202
|
|
|
136
203
|
The browser runtime intentionally does not promise full three.js compatibility yet.
|
|
@@ -138,6 +205,7 @@ The browser runtime intentionally does not promise full three.js compatibility y
|
|
|
138
205
|
- There is no Ruby-native OpenGL, Vulkan, WebGPU, or software renderer.
|
|
139
206
|
- Rendering is delegated to three.js through ruby.wasm.
|
|
140
207
|
- Addon wrappers only work when their JavaScript constructors are registered on `globalThis`.
|
|
208
|
+
- The JavaScript boot module is still required to import ES modules and start ruby.wasm, even though ordinary Ruby scene entrypoints can stay Ruby-only.
|
|
141
209
|
- The first public scope does not include stable APIs for every loader, material, render target, postprocessing pass, WebGPU, or XR workflow.
|
|
142
210
|
- `examples/browser/shared/boot.mjs` is a reference implementation for this repository's examples, not a separate stable package.
|
|
143
211
|
- `preserveDrawingBuffer: true` is useful for deterministic canvas smoke tests, but applications do not need it by default.
|
|
@@ -122,7 +122,7 @@ Local source locations:
|
|
|
122
122
|
|
|
123
123
|
The existing glTF browser smoke test verifies:
|
|
124
124
|
|
|
125
|
-
- `Three::Loaders::GLTFLoader` loads `examples/browser/assets
|
|
125
|
+
- `Three::Loaders::GLTFLoader` loads assets from `examples/browser/gltf/assets/`.
|
|
126
126
|
- The returned `gltf.scene` can be added to a Ruby `Scene`.
|
|
127
127
|
- The loaded JavaScript scene renders through `Three::Renderers::ThreeJSRenderer`.
|
|
128
128
|
- The animation loop can mutate the external root transform.
|
data/docs/next-work.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This document is the resume point for the next implementation session. It is intentionally narrower than `docs/implementation-plan.md`: use it to decide what to do next after conversation context is lost.
|
|
4
4
|
|
|
5
|
-
Last updated: 2026-05-
|
|
5
|
+
Last updated: 2026-05-17.
|
|
6
6
|
|
|
7
7
|
## Current Position
|
|
8
8
|
|
|
@@ -26,6 +26,9 @@ Recent completed work:
|
|
|
26
26
|
- `Sprite` / `SpriteMaterial` support with textured billboard marker sync, JSON export/load, resource disposal, and primitives browser smoke coverage.
|
|
27
27
|
- Saved JSON fixture coverage now includes `Sprite` / `SpriteMaterial` so the representative exporter/loader regression fixture matches the current primitive surface.
|
|
28
28
|
- Completed public API and documentation consistency pass for the current browser-first alpha scope.
|
|
29
|
+
- Browser examples were moved to Ruby-only entrypoints that use `Three::Browser` helpers instead of application-level `require "js"` or `JS.global`.
|
|
30
|
+
- Added the `three-rb browser` executable and generator for standalone Ruby-only browser examples.
|
|
31
|
+
- Release install smoke now validates the installed executable and generated browser app shape outside the repository load path.
|
|
29
32
|
- Local release gate and latest `main` CI are green for the `0.1.0` release candidate.
|
|
30
33
|
|
|
31
34
|
Do not start Phase 9 native renderer work yet. The implementation plan still recommends keeping browser rendering delegated to three.js through ruby.wasm until the browser-first API is more stable.
|
|
@@ -39,12 +42,13 @@ This is the best next step because:
|
|
|
39
42
|
- The representative JSON fixture covers the current primitive/material surface, including `Sprite` / `SpriteMaterial`.
|
|
40
43
|
- The public docs now cover release readiness, publishing, browser example coverage, browser runtime boot contract, and the current implemented API scope.
|
|
41
44
|
- `lib/three/version.rb` already contains `0.1.0`.
|
|
42
|
-
- `CHANGELOG.md`
|
|
45
|
+
- `CHANGELOG.md` currently records `## 0.1.0 - 2026-05-15`; if the release date changes before publishing, update that heading during release metadata finalization.
|
|
46
|
+
- The release candidate now includes the Ruby-only browser generator and installed-generator smoke coverage.
|
|
43
47
|
- Further feature scope should wait until after the `0.1.0` release unless an already-advertised example breaks.
|
|
44
48
|
|
|
45
49
|
## Scope
|
|
46
50
|
|
|
47
|
-
For deferred-release maintenance, keep `CHANGELOG.md`, `docs/release-readiness.md`, and this resume point aligned with the implemented release-candidate surface. Do not
|
|
51
|
+
For deferred-release maintenance, keep `CHANGELOG.md`, `docs/release-readiness.md`, and this resume point aligned with the implemented release-candidate surface. Do not tag, push, or publish until the release owner confirms the release window. If the confirmed release date differs from the current changelog heading, update it as release metadata work.
|
|
48
52
|
|
|
49
53
|
When the owner is ready to publish, follow `docs/publishing.md`: confirm the release date, update `CHANGELOG.md`, run `bundle exec rake release:preflight`, commit the metadata update, publish the gem, tag `v0.1.0`, push `main` and the tag, then verify installation from RubyGems.
|
|
50
54
|
|
|
@@ -60,8 +64,8 @@ Candidate targets, in recommended order when there is no stronger product signal
|
|
|
60
64
|
|
|
61
65
|
## Suggested Implementation Plan
|
|
62
66
|
|
|
63
|
-
1. While release is deferred, keep the
|
|
64
|
-
2. When release is confirmed,
|
|
67
|
+
1. While release is deferred, keep the current changelog heading, release-readiness docs, and publishing checklist aligned with the release candidate without changing the version, tag, or published artifact.
|
|
68
|
+
2. When release is confirmed, adjust `CHANGELOG.md` only if the confirmed release date differs from the current heading.
|
|
65
69
|
3. Run `bundle exec rake release:preflight`.
|
|
66
70
|
4. Commit the release metadata with a message that does not include co-author trailers.
|
|
67
71
|
5. Publish and tag using `docs/publishing.md`.
|
data/docs/publishing.md
CHANGED
|
@@ -1,64 +1,160 @@
|
|
|
1
1
|
# Publishing
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This is the manual release checklist for publishing `three-rb` to RubyGems.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`three-rb` is the RubyGems package name. The public Ruby require path is `three`, with `three-rb` kept as a compatibility require shim.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Do not publish until the release owner has confirmed:
|
|
8
|
+
|
|
9
|
+
- The target version.
|
|
10
|
+
- The release date for `CHANGELOG.md`.
|
|
11
|
+
- RubyGems credentials with MFA enabled.
|
|
12
|
+
|
|
13
|
+
## Release Checklist
|
|
14
|
+
|
|
15
|
+
Run these commands from the repository root.
|
|
8
16
|
|
|
9
17
|
```sh
|
|
18
|
+
cd /path/to/three-rb
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Choose the target version before starting. If this is not already the version in `lib/three/version.rb`, update that file first.
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
module Three
|
|
25
|
+
VERSION = "X.Y.Z"
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Set the version being released from the code. All later commands use this value.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
VERSION="$(ruby -Ilib -e 'require "three/version"; print Three::VERSION')"
|
|
33
|
+
GEM_FILE="three-rb-${VERSION}.gem"
|
|
34
|
+
TAG="v${VERSION}"
|
|
35
|
+
echo "$VERSION"
|
|
36
|
+
echo "$GEM_FILE"
|
|
37
|
+
echo "$TAG"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Start from the latest clean `main`:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
git switch main
|
|
44
|
+
git pull --ff-only origin main
|
|
10
45
|
git status --short
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`git status --short` should be empty before release metadata changes.
|
|
49
|
+
|
|
50
|
+
Install and audit the Node/browser dependencies:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
11
53
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
12
54
|
pnpm audit --audit-level moderate
|
|
13
55
|
pnpm audit signatures
|
|
14
56
|
pnpm exec playwright install chromium
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Run the full non-publishing release gate:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
15
62
|
bundle exec rake release:preflight
|
|
16
63
|
```
|
|
17
64
|
|
|
18
65
|
`release:preflight` runs Ruby tests, builds and installs the gem into a temporary `GEM_HOME`, runs the install smoke test, runs all browser smoke tests, and builds the gem. It does not publish anything.
|
|
19
66
|
|
|
20
|
-
|
|
67
|
+
Confirm release metadata:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
test "$(ruby -Ilib -e 'require "three/version"; print Three::VERSION')" = "$VERSION"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The command must exit successfully. If it fails, fix `VERSION` or `lib/three/version.rb` before continuing. Do not build or publish a gem until the code version is the intended release version.
|
|
21
74
|
|
|
22
|
-
|
|
75
|
+
Update `CHANGELOG.md` from an unreleased heading to the final release date. Replace `$VERSION` with the actual version value:
|
|
76
|
+
|
|
77
|
+
```md
|
|
78
|
+
## $VERSION - YYYY-MM-DD
|
|
79
|
+
```
|
|
23
80
|
|
|
24
|
-
|
|
25
|
-
2. Change `CHANGELOG.md` from `## 0.1.0 - Unreleased` to the release date.
|
|
26
|
-
3. Run `bundle exec rake release:preflight` again.
|
|
27
|
-
4. Commit the metadata update:
|
|
81
|
+
Run the full gate again after metadata changes:
|
|
28
82
|
|
|
29
83
|
```sh
|
|
30
|
-
|
|
31
|
-
git commit -m "Prepare 0.1.0 release"
|
|
84
|
+
bundle exec rake release:preflight
|
|
32
85
|
```
|
|
33
86
|
|
|
34
|
-
|
|
87
|
+
Commit the release metadata, including `lib/three/version.rb` when it changed. Do not add co-author trailers.
|
|
35
88
|
|
|
36
|
-
|
|
89
|
+
```sh
|
|
90
|
+
git status --short
|
|
91
|
+
git add -A
|
|
92
|
+
git commit -m "Prepare ${VERSION} release"
|
|
93
|
+
```
|
|
37
94
|
|
|
38
|
-
|
|
95
|
+
Build the exact gem artifact that will be pushed:
|
|
39
96
|
|
|
40
97
|
```sh
|
|
41
98
|
gem build three-rb.gemspec
|
|
42
|
-
gem push three-rb-0.1.0.gem
|
|
43
99
|
```
|
|
44
100
|
|
|
45
|
-
|
|
101
|
+
The build output must include the selected version and gem file:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
Name: three-rb
|
|
105
|
+
Version: $VERSION
|
|
106
|
+
File: $GEM_FILE
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Publish to RubyGems:
|
|
46
110
|
|
|
47
111
|
```sh
|
|
48
|
-
|
|
49
|
-
git push origin main
|
|
50
|
-
git push origin v0.1.0
|
|
112
|
+
gem push "$GEM_FILE"
|
|
51
113
|
```
|
|
52
114
|
|
|
53
|
-
|
|
115
|
+
RubyGems MFA is required because the gemspec sets `rubygems_mfa_required`. If RubyGems reports that MFA must be enabled, enable MFA on the publishing account and rerun the same `gem push` command.
|
|
116
|
+
|
|
117
|
+
If `gem push` fails for any reason, stop. Do not create or push the git tag until RubyGems confirms the gem was registered.
|
|
54
118
|
|
|
55
|
-
|
|
119
|
+
After RubyGems prints a successful registration message, create and push the git tag:
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
git tag -a "$TAG" -m "Release ${VERSION}"
|
|
123
|
+
git push origin main
|
|
124
|
+
git push origin "$TAG"
|
|
125
|
+
```
|
|
56
126
|
|
|
57
127
|
Verify the public install path from a clean temporary directory:
|
|
58
128
|
|
|
59
129
|
```sh
|
|
60
|
-
|
|
130
|
+
tmpdir="$(mktemp -d)"
|
|
131
|
+
cd "$tmpdir"
|
|
132
|
+
gem install three-rb -v "$VERSION"
|
|
61
133
|
ruby -e 'require "three"; puts Three::VERSION'
|
|
134
|
+
ruby -e 'require "three-rb"; puts Three::VERSION'
|
|
135
|
+
three-rb --help
|
|
136
|
+
three-rb browser examples/browser/quickstart
|
|
137
|
+
test -f examples/browser/quickstart/main.rb
|
|
138
|
+
ruby -e 'main = File.read("examples/browser/quickstart/main.rb"); abort "generated Ruby entrypoint used JS bridge" if main.include?("require \"js\"") || main.include?("JS.global"); puts "generated Ruby entrypoint is Ruby-only"'
|
|
139
|
+
three-rb browser examples/browser/ruby
|
|
140
|
+
test -f examples/browser/ruby/main.rb
|
|
141
|
+
test -f examples/browser/ruby/assets/studio.hdr
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Both Ruby commands must print:
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
$VERSION
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
The `three-rb browser` command must create `examples/browser/quickstart/main.rb` and `examples/browser/ruby/main.rb`, and the final Ruby command must print:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
generated Ruby entrypoint is Ruby-only
|
|
62
154
|
```
|
|
63
155
|
|
|
64
|
-
Then update issue tracker or release notes with the published RubyGems URL
|
|
156
|
+
Then update issue tracker or release notes with the published RubyGems URL:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
https://rubygems.org/gems/three-rb
|
|
160
|
+
```
|
data/docs/release-readiness.md
CHANGED
|
@@ -16,12 +16,13 @@ The `0.1.0` target is complete when all of these are true:
|
|
|
16
16
|
|
|
17
17
|
- Scope is frozen to the browser-first alpha surface in this document and `README.md`; no additional material, loader, render-target, postprocessing, WebGPU, XR, native-renderer, or broad compatibility work is required for the release unless an already-advertised example is broken.
|
|
18
18
|
- Public API documentation matches the implemented, tested Ruby API surface loaded by `require "three"`.
|
|
19
|
+
- Ruby-authored browser examples use `Three::Browser` helpers instead of application-level `require "js"` and `JS.global`, and the `three-rb browser` generator can create the same Ruby-only entrypoint shape for standalone apps.
|
|
19
20
|
- Snake-case Ruby methods are the documented API style. Broad camelCase three.js compatibility aliases are deferred until after `0.1.0`.
|
|
20
21
|
- `Three::Exporters::ThreeJSONExporter` and `Three::Loaders::ThreeJSONLoader` continue to round-trip Ruby-authored scenes covered by the saved `test/fixtures/scene_export_v1.json` regression fixture.
|
|
21
22
|
- JavaScript-loaded assets remain opaque `ExternalObject3D` roots for `0.1.0`; transform-level use, renderer traversal helpers, animation mixer usage, and explicit subtree disposal are in scope, while Ruby child mutation inside loaded external roots is out of scope.
|
|
22
23
|
- Every browser example advertised in `README.md` and `examples/browser/README.md` has a matching deterministic Playwright smoke command, and `pnpm test:browser` runs them all.
|
|
23
24
|
- The required gate below passes locally before tagging, and the CI workflow passes on the release commit.
|
|
24
|
-
- Release metadata is final: `lib/three/version.rb` contains
|
|
25
|
+
- Release metadata is final: `lib/three/version.rb` contains the exact target version, `CHANGELOG.md` has either the unreleased heading during development or the final release date before publishing, and `docs/publishing.md` has the manual publish steps.
|
|
25
26
|
|
|
26
27
|
## Public Scope
|
|
27
28
|
|
|
@@ -29,6 +30,7 @@ Included in the first public scope:
|
|
|
29
30
|
|
|
30
31
|
- Ruby object model for scenes, groups, transforms, cameras, lights, geometries, non-mesh primitives including sprites, common materials including matcap, toon, sprite, and shadow materials, textures, and common math primitives.
|
|
31
32
|
- Browser rendering through `Three::Renderers::ThreeJSRenderer`, ruby.wasm, and `three@0.184.0`.
|
|
33
|
+
- `Three::Browser` helpers and the `three-rb browser` executable for generating standalone Ruby-only browser examples.
|
|
32
34
|
- Dirty-tracked synchronization from Ruby objects into three.js handles.
|
|
33
35
|
- JSON export/load for Ruby-authored scenes.
|
|
34
36
|
- JavaScript-delegated browser integrations for textures, cube maps, RGBE environment maps, glTF, DRACO, animation mixers, OrbitControls, raycasting, instancing, shadows, and initial postprocessing with composer/render/bloom/dot-screen/output passes.
|
|
@@ -67,7 +69,7 @@ The release is acceptable when:
|
|
|
67
69
|
- The required gate passes locally and in CI.
|
|
68
70
|
- `CHANGELOG.md` describes the release as unreleased or tagged with the final date.
|
|
69
71
|
- README documents the browser-first alpha scope and unsupported areas.
|
|
70
|
-
- `bundle exec rake release:gem_smoke` proves the built gem can be installed into a temporary `GEM_HOME
|
|
72
|
+
- `bundle exec rake release:gem_smoke` proves the built gem can be installed into a temporary `GEM_HOME`, used without the repository `lib/` path, and run the installed `three-rb browser` generator.
|
|
71
73
|
- `bundle exec rake release:preflight` proves the Ruby tests, install smoke, browser smoke tests, and gem build pass without publishing.
|
|
72
74
|
- Browser smoke tests cover every advertised browser example.
|
|
73
75
|
|
|
@@ -77,7 +79,7 @@ Before expanding feature scope, prefer:
|
|
|
77
79
|
|
|
78
80
|
1. Keep release checks fast and deterministic.
|
|
79
81
|
2. Keep fixture-based JSON export/load regression tests current.
|
|
80
|
-
3. Keep `CHANGELOG.md` accurate while
|
|
82
|
+
3. Keep `CHANGELOG.md` accurate while the next release remains under an unreleased heading.
|
|
81
83
|
4. Improve public docs around browser examples, browser boot, and unsupported APIs; see `docs/next-work.md`.
|
|
82
84
|
5. Add new material classes, postprocessing passes, render targets, or loaders only when a dedicated example and smoke test need them.
|
|
83
85
|
6. Treat KTX2, WebGPU, WebXR, and native rendering as post-0.1 planning items.
|