OverviewFilesCommitsIssuesDocsReleasesPeers

blender-bridge commits / b895243

Add next-gen bridge design doc covering SVT, material translation, and P2P architecture
Research-backed design covering Blender/Godot/Unreal texture systems, SVT per-texture page table refactor, material node graph walker, and phased implementation plan from bug fixes through P2P collaboration layer. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
b895243c7e52826e618a17246aeb786314ed631c
by plankatron <fleeky@gmail.com> · 2026-03-04T17:48:28.000Z

Changed files (1) +610 -0

docs/plans/2026-03-04-next-gen-bridge-design.md +610 -0
……@@ -0,0 +1,610 @@
1# Blender-Bridge: Next-Gen Design
2
3**Date**: 2026-03-04
4**Status**: Design (pending approval)
5
6---
7
8## 1. Vision
9
10A real-time bidirectional Blender-to-Godot bridge that correctly translates
11materials, textures, and shaders between both applications. Same-machine
12first (SHM+UDS), with P2P extension (Hyperswarm+Autobase) planned for later.
13
14The bridge should be the **only** real-time bidirectional Blender-Godot tool
15in existence — which it already is. This design makes it production-quality.
16
17---
18
19## 2. Research Findings Summary
20
21### 2.1 Competitive Landscape
22
23- **No** real-time bidirectional Blender-Godot bridge exists anywhere else.
24- Closest reference: Unity MeshSync (TCP, custom binary, bidirectional).
25- All other Blender-Godot tools are file-based (glTF export/import).
26- Multi-user Blender tools (Ubisoft Mixer: abandoned, Multi-User addon:
27 active but uses object-level locking, no CRDT).
28- NVIDIA Omniverse: enterprise USD layers + Nucleus server. Not P2P.
29
30### 2.2 Blender Internals (from source code reading)
31
32**Image/Texture architecture** (3 layers):
33- `Image` datablock → `ImBuf` pixel buffers → GPU texture
34- Dual pixel buffers: `byte_buffer` (sRGB RGBA8) + `float_buffer` (linear RGBAF)
35- UDIM: tiles packed into 2D array texture + 1D tile mapping texture
36- `PartialUpdateChecker`: tracks dirty regions for incremental GPU upload
37
38**Material architecture**:
39- `Material` → `bNodeTree` → `bNode` chain → GPU shader
40- Principled BSDF: 31 inputs, each accepts scalar/color OR node connection
41- Multi-material: per-face `material_index` attribute, up to 32766 slots
42- EEVEE compiles node tree → GLSL via `GPUCodegen`
43
44**Texture node types**: TEX_IMAGE (file), TEX_NOISE, TEX_VORONOI, TEX_CHECKER,
45TEX_GRADIENT, TEX_BRICK, TEX_ENVIRONMENT, TEX_GABOR. Each has a Vector input
46(coordinates) and Color/Alpha outputs.
47
48### 2.3 Godot Internals
49
50**Material architecture**:
51- `StandardMaterial3D`: 19 texture slots, 13 feature toggles
52- Internally generates GLSL shader via `_update_shader()` (~1400 lines)
53- Pattern: `final_value = scalar_uniform * texture_sample`
54- `ShaderMaterial`: custom shader + arbitrary uniforms (full control)
55- Cannot mix StandardMaterial3D and ShaderMaterial
56
57**Texture architecture**:
58- `ImageTexture`: CPU Image → GPU upload (simple, full replacement)
59- `RenderingDevice` + `Texture2DRD`: low-level GPU control, sub-region copy
60- `DrawableTexture2D` (4.7+): high-level blit API, no compute shader needed
61
62### 2.4 SVT (Sparse Virtual Textures)
63
64**Terminology**: SVT is the correct general term (Sean Barrett, GDC 2008).
65Our code uses "VT" in class/file names but comments say "SVT". Should be
66consistent.
67
68**How Unreal does it**: Per-texture page table + shared tile cache atlas.
69GPU feedback pass writes `{texture_id, page, mip}`. CPU reads back, loads tiles.
70
71**How Blender's UDIM tiles compare**: Same GPU pattern (indirection → atlas),
72but UDIM tiles are all loaded upfront (not demand-driven). Blender's partial
73update system tracks dirty regions for incremental GPU upload — same concept
74as SVT tile invalidation.
75
76**Godot has no native SVT** but has all building blocks (RenderingDevice,
77Texture2DRD, texture_copy for sub-region updates, compute shaders).
78
79**Hardware sparse textures**: 2025 paper ("The Sad State of Hardware Virtual
80Textures") found tile binding latency is unusable. Software SVT is the
81production standard.
82
83### 2.5 Material Translation (the hard problem)
84
85Blender Principled BSDF → Godot StandardMaterial3D mapping:
86
87**Direct (no loss)**: Base Color, Metallic, Roughness, Normal, Emission,
88Clearcoat Weight/Roughness, Anisotropic, Alpha.
89
90**Lossy**: IOR → specular (math conversion), SSS Weight → SSS strength
91(no per-channel radius), Transmission → refraction (screen-space only).
92
93**Lost (no StandardMaterial3D equivalent)**: Sheen, Specular Tint,
94Coat IOR/Tint/Normal, Subsurface Radius, Thin Film/Iridescence,
95Diffuse Roughness.
96
97**Pattern complexity tiers**:
981. **Simple**: Image Texture → BSDF input (direct slot mapping)
992. **Medium**: Image + Mapping node, packed channel textures (UV params + channel select)
1003. **Complex**: Multi-texture mix, procedurals, custom UV chains (must bake or generate shader)
101
102---
103
104## 3. Architecture
105
106### 3.1 Layer Diagram
107
108```
109┌──────────────────────────────────────────────────────────┐
110│ Layer 4: Material Translation │
111│ Node graph walker → Godot material selection │
112│ Simple → StandardMaterial3D │
113│ Medium → StandardMaterial3D + UV transform │
114│ Complex → Bake first, then treat as Simple │
115├──────────────────────────────────────────────────────────┤
116│ Layer 3: Texture Transfer │
117│ Whole-image: ImBuf → SHM → ImageTexture │
118│ SVT streaming: TileBaker → SHM ring → per-tex PageTable│
119├──────────────────────────────────────────────────────────┤
120│ Layer 2: Scene Sync (existing, working) │
121│ Transforms, geometry, object CRUD │
122│ 44-byte material scalars (albedo, roughness, etc.) │
123├──────────────────────────────────────────────────────────┤
124│ Layer 1: Transport (existing, working) │
125│ SHM dual-region + UDS signaling │
126│ Future: Hyperswarm + Autobase for P2P │
127└──────────────────────────────────────────────────────────┘
128```
129
130### 3.2 Texture Transfer: Two Paths
131
132**Path A: Whole-Image Transfer** (Phase 1 — simple, works now)
133
134```
135Blender Image
136 │ image.pixels.foreach_get() → flat RGBA8 bytes
137 │ OR float_buffer → convert to RGBA8
138 v
139SHM blob (after geometry+material data in object blob)
140 │ [uint32 img_width][uint32 img_height][uint8 rgba_data[w*h*4]]
141 v
142Godot import_changes()
143 │ Image::create_from_data(w, h, false, FORMAT_RGBA8, data)
144 │ ImageTexture::create_from_image(img)
145 v
146StandardMaterial3D::set_texture(TEXTURE_ALBEDO, tex)
147```
148
149- Pro: Simple, correct, no SVT complexity
150- Con: Full image retransmit on any edit, memory proportional to total textures
151- Good for: <10 textures, <4K resolution, same-machine
152
153**Path B: SVT Tile Streaming** (Phase 2 — existing infra, needs per-texture fix)
154
155```
156Blender Image
157 │ TileBaker extracts 128×128 RGBA8 tiles
158 │ PartialUpdate dirty regions → only re-bake changed tiles
159 v
160SHM Tile Ring (8 MB circular buffer)
161 │ tile_ready:{texture_id, tx, ty, mip, offset, size} via UDS
162 v
163VirtualTexture node
164 │ PageTable[texture_id] maps (mip, tx, ty) → PhysicalLocation
165 │ TileCache (shared atlas, LRU eviction)
166 │ upload_tile() → texture_copy() to atlas
167 v
168Per-mesh ShaderMaterial
169 │ Shader selects page_table by texture_id uniform
170 │ UV → virtual tile → page table lookup → atlas sample
171```
172
173- Pro: Fixed memory budget, incremental updates, scales to many/large textures
174- Con: More complex, requires per-texture page table refactor, custom shader
175- Good for: >10 textures, >4K resolution, future P2P streaming
176
177### 3.3 SVT Per-Texture Page Table Refactor
178
179Current (broken):
180```cpp
181class VirtualTexture {
182 PageTable _page_table; // ONE global — textures overwrite each other
183 TileCache _tile_cache; // Shared atlas — correct
184};
185```
186
187Fixed:
188```cpp
189class VirtualTexture {
190 std::vector<PageTable> _page_tables; // One per registered texture
191 std::vector<RID> _page_table_rids; // One GPU texture per page table
192 std::vector<Ref<Texture2DRD>> _pt_textures; // Wrapped for shader use
193 TileCache _tile_cache; // Shared atlas — stays shared
194};
195```
196
197Shader changes:
198```glsl
199// Current (broken): single page table
200uniform sampler2D vt_page_table;
201
202// Fixed: per-mesh page table selection
203uniform sampler2D page_table; // Set per-mesh to the right texture's page table
204uniform sampler2D tile_atlas; // Shared across all meshes
205```
206
207The `create_vt_material()` method would take the texture_id and set the
208correct page table texture as a shader parameter on the returned ShaderMaterial.
209
210### 3.4 Material Node Graph Walker
211
212New component in `change_detector.py` (or new file `material_analyzer.py`):
213
214```python
215def analyze_material(material) -> MaterialDesc:
216 """Walk a Blender material node tree and classify it.
217
218 Returns a MaterialDesc with:
219 - tier: SIMPLE, MEDIUM, COMPLEX
220 - scalar_values: dict of BSDF input defaults
221 - texture_slots: list of (input_name, image_name, uv_settings)
222 - features_needed: set of Godot features to enable
223 """
224 tree = material.node_tree
225 bsdf = find_principled_bsdf(tree)
226 if bsdf is None:
227 return MaterialDesc(tier=COMPLEX) # Non-standard material
228
229 desc = MaterialDesc(tier=SIMPLE)
230
231 for input in bsdf.inputs:
232 if not input.is_linked:
233 # Scalar/color default value
234 desc.scalar_values[input.name] = input.default_value
235 else:
236 # Trace the connection
237 from_node = input.links[0].from_node
238 chain = trace_node_chain(from_node)
239
240 if is_simple_image(chain):
241 # Direct Image Texture → BSDF input
242 desc.texture_slots.append(TextureSlot(
243 bsdf_input=input.name,
244 image=chain.image,
245 uv_source='UV',
246 ))
247 elif is_image_with_mapping(chain):
248 # Image Texture → Mapping → BSDF input
249 desc.tier = max(desc.tier, MEDIUM)
250 desc.texture_slots.append(TextureSlot(
251 bsdf_input=input.name,
252 image=chain.image,
253 uv_source='UV',
254 uv_transform=chain.mapping_params,
255 ))
256 else:
257 # Complex: procedural, mix, math chain
258 desc.tier = COMPLEX
259
260 return desc
261```
262
263### 3.5 Material Blob Format (extended)
264
265Current: 44 bytes (scalars only, no texture references)
266
267Extended format for texture support:
268
269```
270[uint32 has_material]
271if has_material:
272 [float32[4] base_color] 16 bytes
273 [float32 roughness] 4 bytes
274 [float32 metallic] 4 bytes
275 [float32[4] emission_color] 16 bytes
276 [float32 emission_strength] 4 bytes
277 --- existing 44 bytes above ---
278 [float32 ior] 4 bytes (NEW)
279 [float32 clearcoat] 4 bytes (NEW)
280 [float32 clearcoat_roughness] 4 bytes (NEW)
281 [float32 alpha] 4 bytes (NEW)
282 [uint8 tier] 1 byte (NEW: 0=SIMPLE, 1=MEDIUM, 2=COMPLEX)
283 [uint8 texture_count] 1 byte (NEW: 0-8)
284 [uint8[2] _pad] 2 bytes
285 --- total scalars: 64 bytes ---
286
287 for each texture:
288 [uint8 slot] 1 byte (BSDF input: 0=albedo, 1=metallic, ...)
289 [uint8 channel] 1 byte (0=RGBA, 1=R, 2=G, 3=B, 4=A)
290 [uint16 image_name_len] 2 bytes
291 [char[] image_name] N bytes (UTF-8, padded to 4-byte align)
292 [float32[6] uv_transform] 24 bytes (location xyz + scale xyz, or zeros)
293```
294
295This tells Godot: "this mesh uses these textures from these BSDF inputs".
296Godot can then look up whether the image has been transferred (whole-image
297or SVT) and create the appropriate material.
298
299---
300
301## 4. Phased Implementation
302
303### Phase 0: Bug Fixes + Rename (immediate)
304
305**0A. Revert dead texture_id code (B5)**
306- Remove 4-byte `texture_id` from material blob writers (3 spots in C++, 1 in Python)
307- Remove `texture_id` read in `import_changes()` and `scene_import.py`
308- Revert all `48` → `44` size checks
309- Remove `_texture_lookup`, `set_texture_lookup()`, `mark_texture_objects_dirty()`
310
311**0B. Fix SVT material application (B3)**
312- Remove VT material conditional in `import_changes()` (lines 1101-1113)
313- Always use StandardMaterial3D for now
314- SVT materials will be re-enabled in Phase 2 with per-texture page tables
315
316**0C. Fix reconnect texture loss (B4)**
317- Clear `_baker._texture_ids` in `_attempt_reconnect()` so textures re-register
318
319**0D. Rename VT → SVT consistently**
320- Variable names: `_vt_shader` → `_svt_shader`, `vt_lookup.gdshader` → `svt_lookup.gdshader`
321- Method names: `create_vt_material()` → `create_svt_material()`
322- File names: `vt_lookup.gdshader` → `svt_lookup.gdshader`
323- Comments and SPEC.md references
324
325**0E. Update SPEC.md**
326- Section 3.4: Confirm 44-byte material format
327- Section 7: Rename VT → SVT throughout
328- Mark B3, B4, B5 as fixed
329
330### Phase 1: Whole-Image Texture Transfer
331
332**1A. Material node graph walker** (`blender_addon/material_analyzer.py`)
333- Walk Principled BSDF inputs
334- Classify as SIMPLE / MEDIUM / COMPLEX
335- Extract scalar values + texture slot info
336- Return structured `MaterialDesc`
337
338**1B. Image transfer via SHM**
339- Add `image_transfer` UDS message type
340- Blender sends: `image_data:{name},{width},{height},{format},{offset},{size}`
341- Image pixels written to Region 1 blob area (after object data)
342- Godot reads: `Image::create_from_data()` → `ImageTexture::create_from_image()`
343
344**1C. Extended material blob**
345- Extend 44 → 64 byte scalar section (add IOR, clearcoat, alpha)
346- Add texture reference list (slot + image_name per texture)
347- Godot reads texture refs, looks up transferred images, assigns to material
348
349**1D. StandardMaterial3D texture assignment**
350- Map BSDF input names to Godot texture slots
351- Enable required features (`FEATURE_NORMAL_MAPPING`, etc.)
352- Apply IOR → specular conversion
353
354**1E. Blender → Godot texture paint sync**
355- Detect image edits via `depsgraph_update_post` (existing `_dirty_images`)
356- Re-transfer dirty images (whole-image for Phase 1)
357
358### Phase 2: SVT Per-Texture Page Tables
359
360**2A. Refactor VirtualTexture**
361- `std::vector<PageTable>` instead of single `PageTable`
362- Per-texture GPU page table textures
363- Per-texture `Texture2DRD` wrappers
364
365**2B. Update SVT shader**
366- `svt_lookup.gdshader`: accept per-mesh `page_table` uniform
367- Shared `tile_atlas` uniform
368- Proper indirection: UV → virtual tile → page table lookup → atlas sample
369
370**2C. Update TileBaker**
371- Use Blender `PartialUpdateChecker` pattern (dirty regions only)
372- Send only changed tiles after texture paint edits
373- Mip chain generation for each texture independently
374
375**2D. Material creation with SVT**
376- When SVT is active for a texture, use ShaderMaterial with SVT shader
377- Set per-mesh page table uniform based on texture_id
378- Fallback to StandardMaterial3D when SVT not needed
379
380**2E. Demand-driven tile loading (feedback buffer)**
381- Implement GPU feedback pass in Godot (compute shader)
382- Read back tile requests
383- Send requests to Blender via UDS
384- Blender bakes and sends only requested tiles
385
386### Phase 3: Advanced Material Translation
387
388**3A. UV transform support**
389- Transfer Blender Mapping node params (location, rotation, scale)
390- Apply in Godot material (UV transform in StandardMaterial3D or shader)
391
392**3B. Multi-material meshes**
393- Per-face material_index in mesh data
394- Multiple surfaces in Godot ArrayMesh
395- Per-surface material assignment
396
397**3C. Procedural texture baking**
398- Detect procedural texture chains
399- Auto-bake in Blender to image
400- Transfer baked image
401- Re-bake on parameter change
402
403**3D. Complex material → ShaderMaterial generation**
404- Walk node graph → emit Godot Shading Language
405- Handle common patterns: MixRGB, ColorRamp, Math nodes
406- Fallback: bake to textures
407
408### Phase 4: P2P Extension (future)
409
410**4A. Autobase scene graph**
411- Each participant has a Hypercore writer
412- Autobase linearizes into consistent scene view
413- Property-level LWW (like Figma) for conflict resolution
414
415**4B. Hyperdrive for assets**
416- Mesh geometry and textures as content-addressed blobs
417- Sparse replication (only download what's needed)
418
419**4C. SVT over Hyperswarm**
420- Tile requests sent as P2P messages instead of UDS
421- Tile responses streamed via encrypted Hyperswarm connections
422- UASTC/KTX2 compression for network transfer
423
424**4D. Multi-Blender collaboration**
425- Multiple Blender instances as Autobase writers
426- Godot as downstream consumer
427- Kleppmann-style movable tree CRDT for scene graph invariants
428
429---
430
431## 5. Blender-Godot Material Property Mapping (Complete)
432
433### 5.1 Safe 1:1 Mappings
434
435| Blender Principled BSDF | Godot StandardMaterial3D | Notes |
436|---|---|---|
437| Base Color (default) | `albedo` Color | Direct |
438| Base Color (image) | `TEXTURE_ALBEDO` | Direct |
439| Metallic (default) | `metallic` float | Direct |
440| Metallic (image) | `TEXTURE_METALLIC` + channel | Direct |
441| Roughness (default) | `roughness` float | Direct |
442| Roughness (image) | `TEXTURE_ROUGHNESS` + channel | Direct |
443| Normal (image → Normal Map) | `TEXTURE_NORMAL` + `normal_scale` | Enable `FEATURE_NORMAL_MAPPING` |
444| Emission Color | `emission` Color | Enable `FEATURE_EMISSION` |
445| Emission Strength | `emission_energy_multiplier` | Direct |
446| Emission (image) | `TEXTURE_EMISSION` | Direct |
447| Coat Weight | `clearcoat` float | Enable `FEATURE_CLEARCOAT` |
448| Coat Roughness | `clearcoat_roughness` float | Direct |
449| Anisotropic | `anisotropy` float | Enable `FEATURE_ANISOTROPY` |
450| Alpha | `albedo.a` | Enable transparency mode |
451
452### 5.2 Lossy Mappings (approximation)
453
454| Blender | Godot | Conversion |
455|---|---|---|
456| IOR | `specular` float | `specular = ((ior-1)/(ior+1))^2 / 0.08` |
457| SSS Weight | `sss_strength` float | Enable `FEATURE_SSS` |
458| Transmission Weight | `refraction` float | Enable `FEATURE_REFRACTION` (screen-space only) |
459
460### 5.3 Lost Properties (no StandardMaterial3D equivalent)
461
462Sheen (weight/roughness/tint), Specular Tint, Coat IOR, Coat Tint,
463Coat Normal, Subsurface Radius (per-channel), Subsurface Scale,
464Subsurface Anisotropy, Thin Film/Iridescence, Diffuse Roughness.
465
466These require ShaderMaterial (Phase 3) or are silently dropped.
467
468---
469
470## 6. SVT vs Blender UDIM: Divergence Analysis
471
472| Aspect | Blender UDIM | SVT (Unreal-style) | Our Bridge |
473|---|---|---|---|
474| Purpose | UV-space partitioning | Demand-driven streaming | Streaming across process boundary |
475| Tile size | Variable per tile | Fixed (128²/256²) | Fixed 128² |
476| Loading | All tiles upfront | Only visible tiles | Push-based (Phase 2E: demand-driven) |
477| Memory | Proportional to total | Fixed budget (LRU) | Fixed budget (LRU) |
478| Multi-texture | Separate GPU texture per Image | Per-texture page table | Per-texture page table (Phase 2) |
479| Dirty tracking | PartialUpdateChecker (region rects) | Feedback buffer (tile IDs) | Both: Blender partial → tile invalidate |
480| Mip selection | Standard GPU mipmaps | Per-tile mip in page table | Per-tile mip in page table |
481| GPU pattern | 2D array + tile mapping texture | Page table texture + atlas | Page table texture + atlas |
482
483**Key insight**: Both use indirection → physical atlas, but for different
484reasons. Blender's is spatial (artist-authored UV regions). SVT's is temporal
485(load what's needed now). For a bridge, we use SVT's temporal model driven by
486Blender's spatial dirty tracking.
487
488---
489
490## 7. Files Changed (Phase 0 + Phase 1)
491
492| File | Phase | Changes |
493|---|---|---|
494| `src/blender_bridge.cpp` | 0 | Remove texture_id write/read, disable SVT material, rename VT→SVT |
495| `src/virtual_texture.h` | 0 | Rename VT→SVT in comments |
496| `src/virtual_texture.cpp` | 0 | Rename methods, keep infra intact |
497| `blender_addon/__init__.py` | 0 | Remove set_texture_lookup, clear baker IDs on reconnect |
498| `blender_addon/change_detector.py` | 0 | Remove _texture_lookup, mark_texture_objects_dirty |
499| `blender_addon/scene_import.py` | 0 | Revert 48→44 byte reads |
500| `docs/SPEC.md` | 0 | Update material format, rename VT→SVT, mark bugs fixed |
501| `blender_addon/material_analyzer.py` | 1 | NEW: node graph walker |
502| `src/blender_bridge.cpp` | 1 | Extended material blob read, image transfer, texture assignment |
503| `blender_addon/change_detector.py` | 1 | Extended material blob write, texture slot info |
504| `blender_addon/__init__.py` | 1 | Image transfer UDS messages, dirty image re-transfer |
505
506---
507
508## 8. Skill Creation (from cloned repos)
509
510Repos cloned during research:
511- `/storage/projects/code/godot/blender-source/` (2 GB) — Blender source
512- `/storage/projects/code/godot/blender-manual/` (576 MB) — Blender docs
513
514### Skills to create:
515
5161. **blender-image-system** — Image, ImBuf, PartialUpdateChecker, GPU textures
517 Source: `source/blender/blenkernel/intern/image*.cc`, `BKE_image*.hh`
518
5192. **blender-material-nodes** — Material, NodeTree, Principled BSDF, EEVEE compilation
520 Source: `source/blender/nodes/shader/`, `DNA_material_types.h`
521
5223. **blender-depsgraph** — Dependency graph, change detection
523 Source: `source/blender/depsgraph/`
524
5254. **blender-coordinate-system** — Z-up RH, transform matrices, axis conventions
526 Source: `source/blender/io/`, coordinate conversion code
527
5285. **blender-python-api** — bpy.types.Image, Material, Object, Mesh
529 Source: `source/blender/makesrna/intern/rna_image.cc`, `rna_material.cc`
530
531---
532
533## 9. Test Infrastructure
534
535### Phase 0 verification:
536```bash
537scons -j$(nproc) && ./test/test_shm && ./test/test_uds && \
538./test/test_page_table && ./test/test_tile_cache && \
539./test/test_tile_requests && ./test/test_validation
540python3 test/test_python_shm.py && python3 test/test_tile_baker.py
541grep -rn "cursor + 48\|texture_lookup\|mark_texture_objects_dirty" \
542 src/ blender_addon/
543```
544
545### Phase 1 new tests:
546- `test/test_material_analyzer.py` — node graph walking, tier classification
547- `test/test_image_transfer.py` — SHM image write/read round-trip
548- `test/test_material_mapping.py` — Blender BSDF → Godot StandardMaterial3D
549- `test/test_bridge_cli.gd` — Godot headless: material + texture assignment
550
551### Phase 2 new tests:
552- Per-texture page table unit tests
553- SVT shader rendering test
554- Multi-texture tile streaming test
555
556---
557
558## 10. Open Questions
559
5601. **Image format for SHM transfer**: RGBA8 (4 bytes/px, 16 MB for 4K) vs
561 compressed (UASTC ~1 byte/px, 4 MB for 4K)? RGBA8 is simpler for Phase 1.
562
5632. **Color space handling**: Blender stores linear float internally, Godot
564 expects sRGB for albedo textures. Must convert during transfer. Data
565 textures (normal, roughness) stay linear.
566
5673. **Max concurrent images**: SHM Region 1 is 8 MB default. A single 2K
568 RGBA8 image is 16 MB. Need SHM resize for image transfer, or use a
569 separate SHM segment for images.
570
5714. **Multi-surface mesh support**: Current bridge only exports surface 0.
572 Phase 3 adds per-face material_index → multiple Godot surfaces.
573
5745. **SVT shader vs StandardMaterial3D**: When SVT is active for a texture,
575 we must use ShaderMaterial (custom sampling). This means losing some
576 StandardMaterial3D features unless we replicate them in the SVT shader.
577 Alternative: use StandardMaterial3D for scalars + next_pass ShaderMaterial
578 for SVT texture overlay.
579
580---
581
582## 11. Future: P2P Architecture (not in scope, for reference)
583
584```
585Layer 0: Hyperswarm + UDX (transport)
586Layer 1: Autobase + Hyperbee (scene graph state, property-level LWW)
587Layer 2: Hyperdrive (binary assets, content-addressed)
588Layer 3: Ephemeral presence (UDX, lossy)
589Layer 4: Bridge protocol (SHM for local, Autobase for P2P)
590```
591
592Migration: SHM stays as local fast path. Autobase adds P2P. Scene operations
593dual-written to both. Loro-style movable tree CRDT logic in Autobase apply
594handler for cycle-free scene graph invariants.
595
596---
597
598## 12. Success Criteria
599
600**Phase 0**: All 5 active bugs fixed. VT→SVT renamed. All 150+ tests pass.
601Dead code removed. SPEC.md accurate.
602
603**Phase 1**: Blender materials with image textures render correctly in Godot
604with StandardMaterial3D. Albedo, normal, roughness, metallic, emission
605texture maps all transfer via SHM. Texture paint edits sync in real-time
606(whole-image re-transfer). No SVT involved yet.
607
608**Phase 2**: SVT works with multiple textures simultaneously. Per-texture
609page tables. Tile-level incremental updates. Texture paint edits only
610re-transfer changed tiles. Fixed memory budget regardless of texture count.