ThreeBrowser Studio adopts Blender's durable authoring concepts without copying Blender's panel UI or pretending Three.js is Cycles. The editor remains LLM-first: every mutation names exact stable IDs, every batch is atomic, and no operation depends on selection, mode, mouse position, or the active editor.
The machine-readable domain source of truth is
src/blender/catalog.mjs. The pinned Blender 5.2
modifier inventory lives beside it in
src/blender/modifier-inventory.mjs.
The domain catalog labels capabilities implemented, partial, planned,
bake-required, or not-applicable. Query it live with:
{
"query": "blenderCatalog",
"selector": { "kind": "modifiers" },
"limit": 200
}For the modifiers domain, catalog.modifierInventory contains the matching
modifier rows and catalog.modifierInventorySummary contains exact counts.
Use selector.name to search labels, RNA classes, or operator type identifiers.
Blender's central distinction is between an Object (transform, hierarchy, visibility, modifiers and constraints) and reusable Object Data such as a mesh, camera or light. Studio preserves that split as entity documents plus stable-ID resources. Multiple mesh entities can reference the same geometry or material without duplicating it. This follows Blender's documented Object/Object Data model and its database-oriented Python data access.
Blender operators often depend on context—selection, mode, area and active object. Studio follows the data API side of Blender instead: MCP commands name the scene, entity, resource and property explicitly. The distinction matters because Blender itself documents operators separately from direct data access and context-sensitive operators.
| Blender concept | Studio representation | Current execution |
|---|---|---|
.blend data-block database |
Project, scenes, stable-ID resources, scripts and graphs | Partial |
| Scene | Scene document, roots, world-like settings, timeline and active camera | Partial |
| Collection | Group entity as a transform hierarchy | Planned as independent many-to-many membership |
| View Layer | Single active compiled scene view | Planned |
| Object | Entity document | Implemented for the declared entity kinds |
| Mesh data | Shared geometry resource | Procedural, explicit indexed, and canonical editable polygon/corner meshes |
| Materials | Shared basic/standard/physical/toon resource | Scalar PBR, supported bounded raster maps, and supported live node graphs |
| Modifier stack | entity.components.modifiers[] in authored order |
Array/Mirror/Pattern plus ten bounded geometry evaluators; all other Blender types use an explicit validated bake boundary |
| Constraint stack | entity.components.constraints[] in authored order |
Aim/copy/limit subset |
| Action/F-curves | Animation resource with stable target/property tracks | Frame/second keyframes and four interpolations |
| Geometry Nodes | Typed graph IR | Validation only |
| Shader Editor | Typed shader graph IR | Blender RNA core compiles to TSL/WebGPU; unsupported nodes fail explicitly |
| Compositor/View Layers | Future render graph and named passes | Beauty pass only |
| Physics | Ordered Ocean geometry modifier; future solver adapter/cache resources | Bounded deterministic Ocean displacement only; no physics world or general solver |
| Python | Project-owned validated .mjs design |
Stored/validated internally, not executed |
Collections and view layers are not the same thing as parenting. Blender lets an object belong to multiple Collections, while View Layers control evaluation and rendering. Studio therefore does not mislabel a group entity as full collection parity; the catalog keeps those capabilities explicitly planned.
Geometry resources currently compile these recipes:
- box, plane, sphere, capsule, circle, cone and cylinder;
- torus and torus knot;
- lathe profiles;
- Catmull–Rom tube paths;
- 2D shapes with holes and beveled extrusion; and
- explicit/indexed buffer geometry; and
- canonical editable polygon meshes with per-corner UV/color layers, material slots, sharp edges, creases, and hash-guarded vertex/face/edge edits.
Studio now has a bounded editable-mesh kernel for exact vertex transforms, smoothing, face subdivision/inset/individual extrusion/deletion, pairwise manifold edge bevels, and exact vertex merges. Region extrusion, arbitrary loop cuts/dissolve, sculpting, and adjacency-dependent live modifiers over split UV seams remain explicit bake boundaries rather than approximations.
The same guarded edit path directly creates, deletes, renames, activates, projects, transforms, and sets per-corner UV/color layers; assigns per-face material slots; and edits sharp edges and crease weights. Multiple layers stay canonical, but only the active UV and active color layer compile into the current viewport; the active UV becomes raster channel 0. Crease weights are storage/editing data only until a seam-safe subdivision lowering consumes them.
Blender defines modifiers as ordered, non-destructive operations evaluated
top-to-bottom. Studio preserves that model in canonical data. Use
three_studio_inspect with query: "modifierDigest" to obtain the exact
stackHash, then apply guarded modifier.create, modifier.patch,
modifier.move, modifier.delete, or one atomic modifier.stack.edit batch.
The live canonical types are strict: Array, Mirror, Pattern, Triangulate, Weld,
Smooth, Weighted Normal, Edge Split, Solidify, Subdivision, Decimate, Displace,
and Ocean. Ocean is a deterministic, bounded displacement-only subset over an
existing local-XY surface. It supports seeded timeline motion, but not generated
grids, alternate spectra, caches, foam, or spray; timeline-driven Ocean meshes
stay in raster WebGPU and are excluded from the static RTX triangle scene. A
misspelled type fails validation instead of falling through to a default.
Unsupported Blender modifiers are represented as type: "bakeBoundary" with
an operatorType validated against the complete 83-row Blender inventory and
optional bounded opaque parameters. A bake boundary deliberately stops live
downstream evaluation; it is never treated as approximate geometry. Authored
viewport/render enable flags are preserved, but this does not claim separate
render/evidence evaluation parity. See
Blender's modifier stack.
The inventory is pinned to Blender 5.2 LTS's official
Object Modifier Type Items
enum and the direct bpy.types.Modifier
RNA subclasses, cross-checked against the release branch's
properties_data_modifier.py
Add Modifier menus. That is the exhaustive built-in object-modifier type surface:
83 types split into 17 Modify, 30 Generate, 26 Deform, and 10 Simulate entries.
Blender's API calls the final section “Physics”; Studio uses the modifier
manual's “Simulate” category name. Asset-library Geometry Nodes modifiers are
instances of bpy.types.NodesModifier/NODES, not additional RNA types.
Every row includes its full bpy.types.* RNA identifier, the
bpy.ops.object.modifier_add operator plus exact type enum identifier, a
concise purpose, and one deliberately conservative execution status:
| Status | Count | Meaning |
|---|---|---|
live-runtime |
2 | Executes as non-destructive object/instance evaluation: ARRAY, MIRROR |
live-geometry |
10 | Bounded deterministic indexed-mesh subset: DECIMATE, DISPLACE, EDGE_SPLIT, OCEAN, SMOOTH, SOLIDIFY, SUBSURF, TRIANGULATE, WEIGHTED_NORMAL, WELD |
bake-required |
35 | Preserve a validated explicit boundary and bake evaluated data before expecting downstream live evaluation |
planned |
10 | Geometry Nodes plus the remaining nine solver/physics stack types are catalogued but not executed |
not-applicable |
26 | Grease Pencil modifiers require a stroke/layer object model Studio does not have |
This inventory is discovery and compatibility metadata, not a claim that all 83 types execute or that the ten geometry subsets reproduce every Blender option. The full list remains queryable even when a type is unsupported, so MCP clients can author a validated bake workflow without guessing or silently degrading the scene.
Constraint stacks use the same rule. lookAt/trackTo, copy location,
rotation or scale, and limit location execute as derived transforms. More
complex IK, shrinkwrap, path and bone constraints stay authored/bake-required
until a dependency solver exists.
Blender defines materials, lights and world backgrounds through typed shader node networks. Studio keeps validated shader/texture graphs as canonical data and compiles the supported Blender-shaped procedural/PBR subset directly to Three.js TSL/WebGPU NodeMaterials. The full current Blender node inventory is discoverable; unsupported closures and engine-specific nodes fail clearly rather than degrading to a washed-out approximation. See Blender's shader-node model and Principled BSDF.
Studio also compiles strict inline 1–4-channel dataTexture resources to
shared RGBA8 WebGPU textures for supported basic, standard, physical, and toon
map slots. Encoded albedo/emissive/color maps use sRGB; normal, roughness,
metalness, AO, bump, displacement, alpha/mask, and physical data maps use no
colour space.
Raster maps require an active UV layer. They shade the WebGPU material path but
are not sampled by native RTX hit shading.
Direct color-role map bindings, texture.sample2d, and the bounded Blender
Image Texture node may use linear instead of sRGB when their bytes are already
linear; a graph sampler declaration must exactly match its texture resource.
Image Texture currently compiles flat projection only. Linear/closest filtering
and repeat/extend/mirror extension execute only when the canonical dataTexture
declares the corresponding filter and wrap state. Box, sphere, tube, cubic,
smart, and clip modes fail candidate compilation explicitly. Canonical textures
default to trilinear generated mipmaps, linear magnification, clamp wrapping,
and anisotropy 4;
normalized recipes always contain bounded anisotropy. A direct map is rejected
when a material graph outputs the same property or a surface value that
supersedes that slot; use
one of the live sampler nodes inside that graph. Graph image asset nodes remain
CPU-bake-only. Generic format-v1 texture placeholders remain valid for project
compatibility but cannot enter these live raster paths.
Inline dimensions stop at 512 × 512, but canonical base64 still stops at 700,000 decoded bytes under the one-MiB MCP control request. Consequently, full-resolution three/four-channel sources require a future chunk/blob path. Aggregate canonical recipes stop at 8 MiB serialized and 16 MiB decoded, and each expanded RGBA8 mip chain stops at 1,398,100 GPU bytes.
three_studio_status.capabilities.imageTextures.materialControls exposes the
accepted scalar/vec2 ranges, vertexColors and color-control names, and the
exact neutral multiplier for each mapped slot. This is the Studio equivalent
of checking Blender's material inputs before connecting a texture: unauthored
mapped base/emissive/sheen/specular colors become white, applicable lobe and
intensity controls become 1, normal scales become [1, 1], and displacement
uses scale 1/bias 0. The map-aware table explicitly activates sheen (including
white sheenColor) and preserves white specularColor/unit
specularIntensity, preventing those physical maps from being multiplied away.
Authored controls override these neutral defaults.
The pinned Blender 5.2 inventory distinguishes 115 current Add-menu entries,
100 direct ShaderNode API subclasses, API-only and legacy nodes, and 51 live
TSL nodes. NodeFrame plus bounded node layout metadata preserve tutorial
organization; numeric NodeReroute executes as a typed pass-through. The live
numeric/vector tranche includes Integer Input, Camera Data, Normal, Vector
Rotate, and object-space scalar/vector Displacement. The active render UV layer
now drives UV Map, flat dataTexture Image Texture, and fragment Tangent; named UV
maps, From Instancer, and radial tangents are rejected. Vector Transform handles
direction vectors between OBJECT and WORLD while POINT, NORMAL, and CAMERA modes
remain explicit boundaries. Blackbody and Wavelength use bounded analytic
linear-RGB fits. Radial Tiling executes Blender's sharp regular-segment equations
for a constant integer Sides value and constant zero Roundness, with both
normalized and unnormalized coordinates; connected/non-integer Sides and rounded
segments fail explicitly. World/tangent displacement remains explicitly
rejected. Engine closures, world/volume outputs, and
context-specific nodes remain catalogued with explicit candidate-compile
failure until their runtime contract exists.
The native viewport and evidence renderer use ThreeBrowser's external
three/webgpu runtime. Authored WebGPU materials and shadows stay active.
Current evidence is a beauty PNG; Cycles, EEVEE, OSL, Cryptomatte, volumes,
full compositing and RTX evidence remain capability-gated.
An animation resource is the Studio analogue of a Blender Action:
{
"id": "animation/ball-bounce",
"kind": "animation",
"fps": 24,
"frameStart": 0,
"frameEnd": 48,
"loop": "repeat",
"autoplay": true,
"tracks": [{
"targetId": "entity/ball",
"property": "transform.position",
"interpolation": "bezier",
"keyframes": [
{ "frame": 0, "value": [0, 0.5, 0] },
{ "frame": 12, "value": [0, 2.5, 0] },
{ "frame": 24, "value": [0, 0.5, 0] }
]
}]
}Supported property paths are position, rotation, scale and visibility.
Interpolation is constant, linear, smooth, or cubic Bezier; loops are once,
repeat, or ping-pong. Evaluation is pure and frame-rate independent. Play can
enter, pause, resume, seek or step Actions, while three_studio_render accepts
timelineFrame for an exact non-canonical scrub. Drivers, arbitrary RNA paths,
NLA blending, bones, morphs and event tracks remain planned. The design follows
Blender's animation model,
Actions, and
NLA.
The executable acceptance workflow combines free sections of Blender Studio's Blender Fundamentals 4.5 LTS:
- Model the stylized watering can with a lathed body and tube-path handle and spout, translating the official watering-can exercise.
- Preserve ordered Array/Mirror modifiers and an explicit bake-required Bevel.
- Assign metallic and matte PBR materials.
- Build Key, Fill and Rim lighting based on the official light-types lesson.
- Aim a 52 mm active camera with a stable-ID constraint.
- Author the official 0/12/24/36/48 bouncing-ball key sequence.
- Dry-run one 39-operation MCP changeset, commit it atomically, validate the whole project, render frames 1, 7 and 13, then save.
With the native Studio window running:
cd <absolute-repository-path>
npm run tutorial:blenderThe checked-in runner refuses to overwrite a populated project. Supply a fresh managed directory name as its positional argument for repeat acceptance runs.
The operation source is
src/tutorials/blender-fundamentals.mjs
and the live runner is
scripts/run-blender-fundamentals.mjs.
They use only the same nine MCP method contracts available to Codex/ChatGPT.
The catalog represents the rest of Blender instead of claiming it works:
- true Collection membership and View Layers;
- context-dependent Edit/Sculpt/Paint modes, automatic UV unwrap/island packing, and armatures;
- live evaluation of the complete modifier and constraint sets;
- the remaining Blender shader/texture nodes and Geometry Nodes execution;
- drivers, NLA layers, shape keys, rigging and motion paths;
- rigid body, cloth, fluid, particles and simulation caches;
- compositor nodes, render layers and diagnostic passes;
- external image/asset import, link/append, local overrides and libraries; and
.blendserialization orbpyexecution.
Those features should be implemented, imported, or baked behind explicit capabilities. They must never be approximated silently.