makepad/libs/model/SURFACE_API.md
Admin d2130e6550 libs: model, mesh_edit, csg, scene, sim, render, xr
Squash of 25 work commits (Sep 1–12):
  237da90  render: the sprite lane hands the screen draw back the way it found it
  895b9a7  particles: an emitter can ride a body's own frame
  914471f  ai-hub: a feed session whose last socket left ends on its idle timeout; skin: parent, skinned centroid and a nodes-only rig for retargets
  3fcccf3  sim: the whole world is implicitly editable, and one seam says where the ground is
  5692fab  sim: the landform world proves itself — walker through the tunnel included
  f4af6df  sim: terrain knows who changed it — a plan layer over player history
  adbb078  render: a water volume can be physics without a picture
  c17480f  render: a non-rigid body may carry its own orientation
  acad401  sim: an agent with no route holds and retries instead of walking into the wall
  22b2bf9  sim + chat: the composed world surface takes a map floor; the chat gets plan tools
  faf8112  web path: the tessellator's lap timer, the trace span and the fusion cycle timer have no clock on the web
  d3472eb  tsdf: the clock-taking XR helpers are native-only — the browser has no depth camera and no Instant
  4946c9e  sim + render: a repaint is not a world edit — colour and glow restyles never rebake the lightmap
  4317f58  sim + render + chat: walk decks as a surface, the filmed body is no obstruction, the brief never asks
  9791279  render: support rigged models and custom materials across viewers
  3ce2792  sim: use deck geometry for collision and sensing
  c8b79ff  Add portable PBR, rig and soft-body authoring support
  108d423  Add transactional polygon modeling and editable asset documents
  38f4d3b  Refine editable modeling and firm yarn character behavior
  08a2637  sim: add entity-owned lights and vehicle headlights
  00d96a7  render: add clustered lights, local shadows and incremental GI
  cf916af  render: import glTF asset extensions and wire clustered GI
  c6d2cca  model: cut transaction memory and raise capacity limits
  41af47a  raytrace: add a CPU probe-ray BVH budget example
  c963d0a  libs: the game sim splits into makepad-scene and makepad-soft-body; render, model, fab and the asset importer retarget

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:31 +02:00

138 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Surface authoring
These are entries in `model.apply.operations`. Each operation has `op` and the
fields below. Unknown and duplicate fields fail. Material IDs are u32 JSON
integers; vertex IDs and pattern seeds are canonical decimal strings. Colors and factors
are finite linear numbers in 0..1. Layer PNG/raw RGB bytes use sRGB for base color
and emissive, linear normalized bytes for data and normal channels. UV0 follows
the image row direction: row zero corresponds to V=0.
Channels: `base_color`, `metallic_roughness`, `normal`, `occlusion`, `emissive`.
Metallic/roughness packs roughness in G and metallic in B. Normal RGB is a
normalized tangent-space vector encoded from -1..1 to 0..1. Occlusion uses R.
- `surface_material {material,base_color?,metallic?,roughness?,normal_scale?,occlusion_strength?,emissive?,emissive_strength?,alpha?,alpha_cutoff?,double_sided?,fur?}`
sets factors while preserving an existing layer stack; on first use it seeds
a `legacy` base-color layer from the material's existing PNG. Unspecified factors use
defaults: base RGBA1, metal0, rough1, normal scale1, AO strength1, emissive RGB0,
strength1, opaque, cutoff0.5, double-sided false. `alpha` is `opaque|mask|blend`.
Normal scale is 0..16; emissive strength is 0..100000. Material must already
exist (the ordinary `material` operation creates one).
This replaces factors rather than patching them: inspect the current material
and repeat its other factors when changing just roughness or emission.
`fur:{length:0.015,density:0.65,scale:180,seed:0}` adds short procedural fur:
length 0.001–0.05 model metres, density 0.05–1, scale 20–1000 strand cells per
metre, integer seed 0–65535. These are also the defaults for omitted fields
inside `fur`. Omitted/null `fur` disables it; repeat it when changing factors.
Fur reuses the mesh and skin weights in at most six shader shells, with
distance reduction, a 12,000 extra-triangle ceiling per model instance and
a 96,000 ceiling per view. It adds no editable strands or collider geometry.
Prefer it for a coat of short fur/fuzz, especially on Quest. Layered rendering
still costs vertex work and overdraw; keep the base mesh economical. Long
hair, individually modeled strands and strand physics need other geometry.
The recipe persists in model source and GLB makepadFur material extras;
generic GLB viewers show the base PBR surface.
- `surface_remove_material {material}` removes the rich sidecar and restores the
legacy material's factors/image. This explicitly removes its retained layers.
- `surface_layer {material,channel,layer,width,height,color?,rgba_hex?,mask_hex?,opacity?,blend?,visible?}`
appends a named layer, or replaces that same layer while retaining stack order.
`color` is linear RGBA, defaulting to the channel's neutral value. `rgba_hex` is
exactly width*height*4 lowercase hex bytes and conflicts with `color`.
Alternatively `{material,channel,layer,png_hex,...}` imports a complete RGBA PNG;
width/height/color/rgba_hex must then be omitted. Optional opacity defaults1,
blend `over|multiply|add|subtract` defaults over, visibility defaults true.
`mask_hex` is one linear byte per pixel. No external image URI is accepted.
- `surface_remove_layer {material,channel,layer}` removes an existing layer.
- `surface_move_layer {material,channel,layer,index}` changes stack order; index is
zero-based in the final stack. Bottom is0, top is last.
- `surface_mask {material,channel,layer,mask_hex}` replaces the mask; null removes
it. A mask byte is coverage0..255, independent of pixel alpha.
- `surface_pattern {material,channel,layer,pattern:{kind,color_a,color_b,scale?,seed?}}`
fills the layer deterministically and retains the pattern recipe. Kind is
`checker|stripes|gradient|noise|perlin|fbm|yarn`; colors are RGBA. Scale
defaults[8,8], each component is >0 and <=4096. Seed defaults"0". Gradient
repeats across U. Perlin is smooth gradient noise, fbm sums four seeded noise
octaves, and yarn forms curved strands with fine fibers. These three patterns
tile continuously at integral scale components; nonintegral scales crop the
field. The original `noise` remains discrete cell noise.
- `surface_derive {material,source_channel,source_layer?,channel,layer,strength?,roughness_min?,roughness_max?,metallic?,wrap?}`
creates/replaces a named `normal` or `metallic_roughness` layer from height.
A legacy base-color PNG is seeded on first use, as with `surface_layer`.
Omit `source_layer` to use the composed visible source channel (bitmap and
procedural layers with their masks/blends); name a layer to use it even when
hidden, including its mask and opacity. Source `base_color`/`emissive` uses
linear-light luminance, `occlusion` uses R, `metallic_roughness` uses G. Normal
maps cannot be height sources. Transparent coverage contributes zero height;
derived data maps are opaque, including neutral normals in empty regions.
Normal output uses centered UV derivatives, positive height toward +Z, and
strength0..16 (default1); constant height gives neutral [128,128,255]. Strength
measures height per UV unit so resolution changes do not change bump amplitude.
A rise toward increasing U or V tilts the corresponding normal component
negative. Worker clients use `SurfaceDerivation::derive_image` for the same
deterministic conversion; this does not change imported/generated normal maps.
`wrap` defaults true and samples opposite edges for periodic height; false
clamps edge samples. Wrapping cannot make a nonperiodic input seamless.
Roughness maps height0..1 to min..max (defaults0.2..0.9); min/max and metallic
(default0) are0..1 and min<=max. Output packs roughness in G and metallic in B;
R is255. Deriving sets the target normal-scale or metal/rough factors to1 so
the declared output is applied once. Existing target mask, blend, opacity and
visibility are retained (a mask of incompatible dimensions is removed).
The height source and its recipes remain intact. The output retains its
derivation recipe and pixels as a **snapshot**: rerun `surface_derive` after
source edits; there is no implicit dependency refresh. Replacing the source
itself is rejected. Painting/pattern/dilation of derived pixels clears their
derivation recipe. No image byte payload is required by this operation.
- `surface_stroke {material,channel,layer,points,radius,color,hardness?,opacity?,mask?}`
paints the continuous UV polyline with1..256 two-component points. Radius is
positive in UV units; hardness defaults0.5, opacity1, mask false. Hardness0 is a
linear radial falloff and1 is a hard disk. Mask painting uses color.R.
- `surface_projected_stroke {object,material,channel,layer,origin,direction,radius,depth,color,hardness?,opacity?,mask?}`
projects one circular brush through a cylinder on front-facing visible
triangles. Origin/direction are 3-vectors in supplied mesh coordinates, radius
and positive depth use the same units. The document host evaluates scene
coordinates before invoking this operation. Multiple operations form a stroke.
- `surface_vertex_paint {object,vertices,color,opacity?}` blends linear RGBA into
stable vertex IDs (default white). New vertices produced by geometry edits
receive closest-source-surface barycentric color interpolation. Derived LODs
preserve paint and resample moved/new vertices from the source surface; the
editable mesh and its paint remain unchanged.
- `surface_bake {source,target,material,channel,layer,width,height,max_distance,ao_samples?,ao_distance?,dilation?}`
rasterizes target UV0 and transfers nearest high-resolution source attributes
using a bounded triangle BVH. Positive max_distance bounds correspondence.
Normal output is tangent-space and includes source normal texture/scale.
Occlusion casts deterministic cosine hemisphere rays:1..64 samples(default16),
positive distance(default1). Base color includes vertex paint and material
factors; metal/rough and HDR emissive factors are also transferred. HDR emission
is normalized into one target strength without clipping. Dilation defaults2.
Bake creates/replaces the named layer and normalizes that channel's target
factors so transferred factors are applied exactly once. No matched texels is
an error. Target UVs must lie in0..1; overlapping UVs producing conflicting
transferred values are rejected. Separate source/target objects may share a
material, in which case editing that shared material affects both.
- `surface_dilate {material,channel,layer,iterations,preserve_alpha?}` propagates
nearest covered neighboring texels by0..64 iterations. Preserve-alpha defaults
true and fills RGB gutters without changing coverage. Bake uses false to fill
uncovered texels. Painting/pattern/dilation invalidates derived mip levels.
- `surface_mips {material,channel,layer}` retains a full mip chain down to1x1.
Color filtering uses linear light and premultiplied alpha; normal vectors are
renormalized; data channels average directly. Odd edge texels are included.
A material supports at most32 layers per channel. Images obey document limits
(default2048 dimension,8MiB decoded RGBA per image); total source, transaction,
worker-memory, and work budgets still apply. Operations check cancellation and
publish state only after all validation succeeds. Source checkpoints retain
pixels, masks, pattern/derivation recipes, layers, vertex colors and requested mip chains.
Compile flattens visible layers, preserves source UVs, emits tangent vectors and
RGBA vertex colors, and embeds PNGs for all five standard glTF PBR channels.
`KHR_materials_emissive_strength` carries HDR strength. Materials preserve alpha
mode, cutoff and double-sided state. Export regenerates channel-aware composite
mips; optional `material.extras.makepadMips` maps standard texture field names to
embedded IMAGE indices for levels1..N. Ordinary glTF clients can use the standard
level-zero image and mip-filtering sampler. Rich skinned materials keep separate
primitive material slots; documents without sidecars retain the legacy shared
opaque atlas contract. All GLB resources are self-contained.
Vertex paint targets owned mesh vertices. Run `make_unique` before painting a
linked instance independently; baking and projected strokes evaluate linked
source geometry through its object transform.