Skip to content

Commit e4d6b64

Browse files
authored
feat: native 3D splat scene rendering
Merge native shared-scene 3D rendering, splat depth improvements, FPS camera speed controls, and release 1.5.9. Remote security checks intentionally bypassed per request.
2 parents de2f7d1 + 7d7a0eb commit e4d6b64

123 files changed

Lines changed: 13009 additions & 4458 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,4 @@ _fremd/
8989

9090
# Windows artifacts
9191
nul
92+
.gstack/

docs/Features/3D-Layers.md

Lines changed: 65 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# 3D Layer System
22

3-
MasterSelects now has two distinct 3D paths:
3+
MasterSelects authorable 3D content now resolves through one shared scene contract.
44

5-
- Stable shared-scene 3D via Three.js for models, primitive meshes, 3D text, camera clips, and the default gaussian-splat route.
6-
- A native WebGPU gaussian-splat renderer that can be enabled per clip when needed.
5+
- The native WebGPU scene is the primary runtime for 3D planes, primitive meshes, 3D text, imported OBJ/glTF/GLB models, camera clips, and native gaussian-splat scene objects.
6+
- Gaussian splat clips render through the native WebGPU scene path and stay inside the same scene camera, object-transform, and effector contract as the rest of the 3D system.
7+
- The old `three.js` bridge has been removed. Native shared-scene rendering is the only active 3D runtime.
78

89
Legacy gaussian-avatar support still exists in code for migration and old project data, but new avatar import is disabled.
910

@@ -12,45 +13,46 @@ Legacy gaussian-avatar support still exists in code for migration and old projec
1213
| Surface | Status | Notes |
1314
|---|---|---|
1415
| Per-layer 3D toggle | Stable | Any normal video/image layer can be switched between 2D and 3D. |
15-
| OBJ / glTF / GLB / FBX model import | Stable | Model clips are always 3D and render through Three.js. |
16-
| Primitive mesh clips | Stable | Cube, sphere, plane, cylinder, torus, cone, and 3D text are created from the Media Panel. |
17-
| Scene camera clips | Stable | Timeline camera clips control the shared Three.js scene. |
18-
| Gaussian splat clips | Stable but specialized | Default route is shared-scene Three.js; native WebGPU rendering is optional. |
19-
| Splat effector clips | Stable but specialized | They deform Three.js splats live at playback time. |
16+
| 3D video/image planes | Stable | `clip.is3D` video and image layers render as scene planes. |
17+
| OBJ / glTF / GLB model import | Stable | Model clips are always 3D and render as shared-scene objects. |
18+
| Primitive mesh clips | Stable | Cube, sphere, plane, cylinder, torus, cone, and 3D text render through the native shared scene. |
19+
| Scene camera clips | Stable | Timeline camera clips drive preview and export scene navigation. |
20+
| Gaussian splat clips | Stable | They render as normal shared-scene objects under the native WebGPU path. |
21+
| Splat effector clips | Stable but specialized | They deform scene-driven splats live at playback time; 3D planes remain excluded in phase 1. |
2022
| Gaussian avatar import | Legacy only | Import is blocked; existing projects may still expose blendshape editing. |
2123
| Temporal / particle splat settings | Experimental | Wired in the engine/export path, but not yet exposed as a dedicated properties tab. |
2224

2325
## Rendering Model
2426

2527
```text
26-
[2D layers] -------------------------------> Existing WebGPU compositor
28+
[2D layers] --------------------------------> Existing WebGPU compositor
2729
|
28-
+--> [3D model / mesh / text / camera / shared-splat layers]
29-
| -> Three.js scene -> OffscreenCanvas -> compositor
30-
|
31-
+--> [Native gaussian-splat clips]
32-
-> GaussianSplatGpuRenderer -> texture -> compositor
30+
+--> [3D planes / meshes / text / models / splats / cameras]
31+
-> Scene layer collection
32+
-> Shared scene camera resolution
33+
-> NativeSceneRenderer
34+
-> one synthetic 3D scene texture
35+
-> compositor
3336
```
3437

35-
Three.js is used as the shared 3D scene for classic 3D layers and for the default gaussian-splat route. The native gaussian-splat renderer is a separate WebGPU path, enabled by the clip-level `useNativeRenderer` setting.
36-
37-
Camera clips and splat effectors only affect the shared Three.js scene. They do not drive the native gaussian-splat renderer.
38+
Prepared splat runtime metadata, native splat rasterization, preview, nested compositions, preload, readiness, and export now all converge on the same scene-layer and scene-camera contract.
3839

3940
## Stable 3D Features
4041

4142
### Per-Layer 3D Toggle
4243

4344
- Any video or image clip can be toggled to 3D from the Transform panel.
44-
- 3D layers become textured planes in the Three.js scene.
45+
- 3D layers become textured planes in the common 3D scene.
4546
- Turning 3D off resets the 3D-specific transform state back to 2D defaults.
4647

4748
### 3D Model Import
4849

49-
- Supported import formats are `.obj`, `.gltf`, `.glb`, and `.fbx`.
50+
- Supported import formats are `.obj`, `.gltf`, and `.glb`.
5051
- Model clips are automatically marked `is3D: true` and cannot be switched back to 2D.
5152
- Models are auto-centered and normalized to fit the viewport.
5253
- Default lighting is Ambient plus Directional lighting.
5354
- The Transform panel exposes a wireframe debug toggle for model clips.
55+
- Imported models use a native runtime/cache path.
5456

5557
### Primitive Meshes and 3D Text
5658

@@ -69,32 +71,33 @@ Create mesh clips from the Media Panel via `+ Add > Mesh` or the context menu:
6971
- Mesh items live in a `Meshes` folder in the Media Panel.
7072
- Dragging a mesh item to the timeline creates a 3D clip with `is3D: true` and `meshType`.
7173
- All transform properties and keyframe animation are supported.
74+
- Primitive meshes and 3D text render through the native shared scene contract.
7275

7376
### Scene Camera
7477

7578
There are two camera concepts in the product:
7679

7780
- Composition camera: project-level camera settings on the composition itself.
78-
- Camera clips: timeline clips that control the shared Three.js scene.
81+
- Camera clips: timeline clips that drive the active shared scene camera.
7982

8083
Camera clips expose their own Properties tab with:
8184

8285
- FOV
8386
- Near plane
8487
- Far plane
8588

86-
The Transform tab also turns into camera-orbit controls for the active scene camera. In FPS mode, the preview accepts WASD/QE navigation plus mouse look.
89+
The Transform tab becomes scene-navigation controls for the active camera clip. In FPS mode, the preview accepts WASD/QE navigation plus mouse look. Free scene navigation now belongs to camera clips rather than gaussian-splat clips.
8790

8891
## Gaussian Splats
8992

90-
Gaussian splat clips are imported from `.ply` and `.splat` files.
93+
Gaussian splat clips are imported through the SuperSplat-compatible `@playcanvas/splat-transform` reader path. Supported scene formats include `.ply`, `.compressed.ply`, `.splat`, `.ksplat`, `.spz`, `.sog`, `.lcc`, and zipped SOG-style `.zip` payloads.
9194

9295
- Clips are created as `is3D: true`.
93-
- The clip-level render tab exposes `useNativeRenderer`, `maxSplats`, `sortFrequency`, `splatScale`, `nearPlane`, and `farPlane`.
94-
- The default renderer is the shared Three.js scene path.
95-
- Native WebGPU rendering is optional and off by default.
96-
- The shared-scene route participates in scene cameras and splat effectors.
97-
- The native route uses its own camera-style navigation controls in the Transform tab.
96+
- The Gaussian tab exposes the native renderer status together with `maxSplats`, `sortFrequency`, `splatScale`, `orientationPreset`, `nearPlane`, and `farPlane`.
97+
- Gaussian splats participate in scene cameras, object transforms, object-level effectors, preview, nested compositions, export, preload, and readiness checks through the same native shared-scene path.
98+
- Realtime splat rendering uses a worker-backed back-to-front order buffer based on the SuperSplat/PlayCanvas sorter approach. Precise export can still fall back to the existing GPU sort path.
99+
- Sequence splats follow the same shared runtime contract and are no longer treated as a permanent legacy-only scene path.
100+
- The Transform tab now exposes normal object transforms for gaussian splats. Scene navigation lives on camera clips.
98101

99102
Some gaussian-splat settings exist in the data model and export pipeline but are not yet surfaced as a full dedicated UI:
100103

@@ -106,14 +109,15 @@ Those are wired through the renderer and export code, but they should still be t
106109

107110
## Splat Effectors
108111

109-
Splat effector clips are timeline clips that only affect Three.js splats.
112+
Splat effector clips are timeline clips that affect scene-driven splats, including native gaussian-splat clips.
110113

111114
- Modes: `repel`, `attract`, `swirl`, and `noise`
112115
- Controls: strength, falloff, speed, and seed
113116
- Transform scale acts as the effector radius
114117
- They do not render visible content on their own
118+
- 3D planes remain excluded in phase 1 for parity with older projects
115119

116-
This is a good example of a specialized 3D feature that is stable in the UI, but limited to the shared-scene splat path.
120+
This is a specialized 3D feature that is stable in the UI and now follows the shared scene contract.
117121

118122
## Legacy Gaussian Avatars
119123

@@ -141,55 +145,60 @@ The Transform tab is context-sensitive:
141145

142146
- For normal 3D layers, it shows position, scale, rotation, opacity, blend mode, and 3D toggles.
143147
- For camera clips, it becomes scene-navigation controls.
144-
- For native gaussian splats, it behaves like orbit/FPS camera controls.
148+
- For gaussian splats, it now behaves like a normal 3D object transform surface plus 3D effector toggle.
145149
- The `Speed` field is explicitly marked WIP in the UI.
146150

147151
## Export
148152

149153
3D layers are included in export.
150154

151-
- Shared-scene 3D models, meshes, text, and default gaussian splats render through the Three.js path.
152-
- Native gaussian splats are handled as a separate WebGPU render target path.
153-
- Export waits for 3D and splat readiness before capture so preview and export stay aligned.
155+
- Scene camera resolution, scene-layer collection, splat runtime preparation, preload, and readiness now share the same scene contract across preview, nested, and export.
156+
- Gaussian splats can export through prepared or direct native scene modes while keeping identical scene-camera semantics.
157+
- Export waits for shared 3D and splat readiness before capture so preview and export stay aligned.
154158

155159
## Key Files
156160

157161
| File | Purpose |
158162
|---|---|
159-
| `src/engine/three/ThreeSceneRenderer.ts` | Shared Three.js scene renderer |
160-
| `src/engine/three/types.ts` | Shared-scene 3D and effector runtime types |
161-
| `src/engine/render/RenderDispatcher.ts` | Route selection for Three.js, native splats, and effectors |
162-
| `src/engine/render/LayerCollector.ts` | Collects renderable layer sources |
163-
| `src/stores/timeline/clip/addModelClip.ts` | Model clip creation |
164-
| `src/stores/timeline/meshClipSlice.ts` | Primitive mesh and 3D text clip creation |
165-
| `src/stores/timeline/cameraClipSlice.ts` | Timeline camera clip creation |
166-
| `src/stores/timeline/clip/addGaussianSplatClip.ts` | Gaussian splat clip creation |
167-
| `src/stores/timeline/splatEffectorClipSlice.ts` | Splat effector clip creation |
168-
| `src/components/panels/properties/TransformTab.tsx` | Context-sensitive 3D transform and camera controls |
163+
| `src/engine/native3d/NativeSceneRenderer.ts` | Shared native 3D scene renderer entrypoint |
164+
| `src/engine/native3d/passes/MeshPass.ts` | Native primitive mesh, imported model, and 3D text render pass |
165+
| `src/engine/native3d/assets/ModelRuntimeCache.ts` | Native OBJ / glTF / GLB runtime cache, centering, and normalization |
166+
| `src/engine/native3d/assets/TextMeshCache.ts` | Native font-outline text mesh cache and extrusion generator |
167+
| `src/engine/scene/types.ts` | Shared scene runtime and effector types |
168+
| `src/engine/scene/SceneCameraUtils.ts` | Shared scene camera resolution |
169+
| `src/engine/scene/SceneEffectorUtils.ts` | Renderer-neutral object-level effector math |
170+
| `src/engine/scene/runtime/SharedSplatRuntimeUtils.ts` | Shared splat runtime request and readiness helpers |
171+
| `src/engine/gaussian/loaders/SplatTransformLoader.ts` | SuperSplat-compatible splat-transform loader adapter |
172+
| `src/engine/gaussian/core/SplatOrderSorter.ts` | Worker-backed realtime splat order buffer |
173+
| `src/engine/render/RenderDispatcher.ts` | Shared scene routing plus splat runtime/readiness integration |
174+
| `src/engine/native3d/passes/EffectorCompute.ts` | Native gaussian-splat effector deformation pass |
175+
| `src/services/layerBuilder/LayerBuilderService.ts` | Scene-layer construction for preview and nested rendering |
176+
| `src/engine/export/ExportLayerBuilder.ts` | Export layer building for shared scene content |
177+
| `src/engine/export/preloadGaussianSplats.ts` | Shared splat preload and export preparation |
178+
| `src/components/panels/properties/TransformTab.tsx` | Context-sensitive 3D transform and scene-navigation controls |
169179
| `src/components/panels/properties/GaussianSplatTab.tsx` | Gaussian splat render settings tab |
170180
| `src/components/panels/properties/CameraTab.tsx` | Scene camera settings tab |
171181
| `src/components/panels/properties/SplatEffectorTab.tsx` | Splat effector settings tab |
172-
| `src/components/panels/properties/BlendshapesTab.tsx` | Legacy gaussian-avatar blendshapes tab |
173-
| `src/engine/featureFlags.ts` | 3D feature flags |
174182

175183
## Supported Formats
176184

177185
| Format | Current support | Notes |
178186
|---|---|---|
179-
| `.obj` | Supported | Imported as a Three.js model clip. |
180-
| `.gltf` | Supported | Imported as a Three.js model clip. |
181-
| `.glb` | Supported | Imported as a Three.js model clip. |
182-
| `.fbx` | Supported | Imported as a Three.js model clip. |
183-
| `.ply` | Supported | Gaussian splat import. |
187+
| `.obj` | Supported | Imported as a 3D model clip in the shared scene contract. |
188+
| `.gltf` | Supported | Imported as a 3D model clip in the shared scene contract. |
189+
| `.glb` | Supported | Imported as a 3D model clip in the shared scene contract. |
190+
| `.fbx` | Not supported | Do not rely on FBX import; no native FBX loader ships today. |
191+
| `.ply` / `.compressed.ply` | Supported | Gaussian splat import with Morton ordering where needed. |
184192
| `.splat` | Supported | Gaussian splat import. |
185-
| `.ksplat` | Not yet supported | Parser stubs exist, but the file is rejected today. |
186-
| `.gsplat-zip` | Not yet supported | Parser stubs exist, but the file is rejected today. |
193+
| `.ksplat` | Supported | Loaded through `@playcanvas/splat-transform`. |
194+
| `.spz` | Supported | Loaded through `@playcanvas/splat-transform`. |
195+
| `.sog` / `.zip` | Supported | Loaded through the bundled SOG/zip reader path. |
196+
| `.lcc` | Supported | The first returned LOD table is used. |
187197
| Gaussian avatar `.zip` | Legacy only | Import is blocked in the current product surface. |
188198

189199
## Limitations
190200

191-
- Native gaussian splats remain an optional path, not the default.
192-
- Temporal and particle splat controls are still partially surfaced in the UI.
193-
- Camera clips control the shared scene; they do not replace composition-level camera settings.
201+
- Temporal and particle splat controls are still only partially surfaced in the UI.
202+
- Composition-level camera settings still remain available alongside camera clips.
194203
- Legacy gaussian-avatar import is disabled.
195-
- `ksplat` and `gsplat-zip` are not supported yet, even though the loader code knows about them.
204+
- Higher-order spherical harmonics are preserved during import, but the current native shader still renders the DC color path only.

docs/Features/Media-Panel.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ Import, organize, and manage media assets with folder structure, proxy generatio
3636

3737
The panel also accepts a few specialized asset types that flow into the timeline as 3D clips:
3838

39-
- `model` files: OBJ, glTF/GLB, FBX
40-
- `gaussian-splat` files: PLY, SPLAT
39+
- `model` files: OBJ, glTF/GLB
40+
- `gaussian-splat` files: PLY, compressed PLY, SPLAT, KSPLAT, SPZ, SOG, LCC, and SOG-style ZIP payloads
4141

4242
Lottie imports are treated as first-class media items. `.json` files are only accepted when their contents actually match Lottie structure, so arbitrary JSON data is not misclassified as animation.
4343

@@ -449,7 +449,7 @@ interface MediaFile {
449449
- Audio-only files restricted to audio tracks
450450
- Files still importing or missing cannot be dragged to timeline
451451
- Compositions cannot be dragged into themselves (active comp check)
452-
- Mesh items create 3D clips with `is3D: true` and `meshType` (rendered via Three.js)
452+
- Mesh items create 3D clips with `is3D: true` and `meshType` (rendered via the shared 3D scene)
453453
454454
### Track Type Enforcement
455455
| Media Type | Allowed Tracks |

docs/Features/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ The docs in this folder were re-audited against the current codebase and now tra
2222
| **Timeline Editing** | Multi-track editing, nested compositions, markers, shortcuts, and keyframes |
2323
| **AI Control** | OpenAI chat with 79 exported tools plus local/native bridge access for external agents |
2424
| **AI Video Workspace** | Classic AI Video plus FlashBoard board-mode generation and media import |
25-
| **3D Layers** | Three.js layers, camera clips, Gaussian splats, and splat effectors |
25+
| **3D Layers** | Shared-scene 3D layers, camera clips, Gaussian splats, and splat effectors |
2626
| **Vector Animation** | Lottie clips with deterministic canvas playback, looping, and export |
2727
| **Audio** | Element-synced playback, drift correction, waveform extraction, EQ, and audio export |
2828
| **Project Storage** | `project.json` source of truth, RAW-copy-first media flow, autosave, relink, backups |
@@ -53,7 +53,7 @@ The docs in this folder were re-audited against the current codebase and now tra
5353
| [Effects](./Effects.md) | Current effect registry, categories, quality controls, and inline effect behavior |
5454
| [Masks](./Masks.md) | Overlay mask editing, feathering, stored modes, and current limitations |
5555
| [Text Clips](./Text-Clips.md) | Canvas-backed text rendering, typography controls, and timeline text items |
56-
| [3D Layers](./3D-Layers.md) | Three.js scene path, native Gaussian splats, cameras, and splat effectors |
56+
| [3D Layers](./3D-Layers.md) | Shared-scene path, native Gaussian splats, cameras, and splat effectors |
5757
| [Vector Animation](./Vector-Animation.md) | Lottie import, runtime playback, looping, and export behavior |
5858
| [Audio](./Audio.md) | Playback sync, EQ, waveform extraction, audio clip behavior, and export |
5959
| [Export](./Export.md) | WebCodecs fast/precise export, FFmpeg intermediates, image/audio-only export, FCPXML, and project-persistent presets |
@@ -84,7 +84,7 @@ The docs in this folder were re-audited against the current codebase and now tra
8484
```text
8585
Frontend React 19 + TypeScript + Vite 7.x
8686
State Zustand with modular timeline and media slices
87-
Rendering WebGPU + WGSL + Three.js for 3D layers
87+
Rendering WebGPU + WGSL + shared-scene 3D runtime
8888
Media MediaBunny, WebCodecs, HTML media fallback paths
8989
Audio Web Audio API, EQ, drift correction, waveform extraction
9090
AI OpenAI chat, Kie.ai, hosted cloud, PiAPI catalog, SAM2, MatAnyone2

0 commit comments

Comments
 (0)