Spaces:
Running
Running
Three.js texture & PBR reference (notebooklm research, 2026-07-22)
Doc-grounded (threejs.org MeshPhysicalMaterial / MeshStandardMaterial / Texture / CanvasTexture /
DataTexture / manual Β§Textures). Drives analyze_texture.py (finish classification + recipe) and
the emitted makeProceduralTextureSet / material presets in generate_threejs_factory.py.
Colour space β get this right or everything looks wrong
- Albedo /
map/emissiveMap/sheenColorMapβTHREE.SRGBColorSpace. - Data maps (
roughnessMap,metalnessMap,normalMap,aoMap,bumpMap,displacementMap,thicknessMap,anisotropyMap) βTHREE.NoColorSpace(linear data, never sRGB). CanvasTexture:flipY = true(default), autoneedsUpdateon construct.DataTexture:flipY = false(default) β memory (0,0) is bottom-left. SetneedsUpdate = true.- After changing
wrapS/wrapTon an already-used texture you MUST setneedsUpdate = true. aoMap/lightMapread UV channel 1 β geometry needs a 2nd UV set, or settexture.channel = 1.- Tiling:
wrapS = wrapT = THREE.RepeatWrapping+repeat.set(u,v); setanisotropy = renderer.capabilities.getMaxAnisotropy()so oblique angles stay sharp.
Per-finish material recipe (MeshPhysicalMaterial scalars)
| finishClass | metalness | roughness | clearcoat | ccRoughness | transmission | ior | envMapIntensity | anisotropy | author maps |
|---|---|---|---|---|---|---|---|---|---|
gemstone (translucent quartz/glass) |
0.0 | 0.05 | 1.0 | 0.0 | 1.0 | 1.54 | 1.0 | 0.0 | map(gradient), thicknessMap |
gem-metal (chromed doppler blade β our blend) |
0.75 | 0.14 | 0.6 | 0.06 | 0.0 | 1.5 | 1.3 | 0.0 | map(gradient+smoke), roughnessMap |
painted-metal (glossy paint) |
0.0 | 0.5 | 1.0 | 0.05 | 0.0 | 1.5 | 1.0 | 0.0 | map, roughnessMap, clearcoatRoughnessMap |
worn-composite (aged rubber/grip) |
0.0 | 0.9 | 0.0 | 0.0 | 0.0 | 1.5 | 0.5 | 0.0 | map(mottled), roughnessMap, bumpMap |
brushed-steel |
1.0 | 0.35 | 0.0 | 0.0 | 0.0 | 1.5 | 1.0 | 1.0 | anisotropyMap, roughnessMap, normalMap |
Note: pure
gemstone(transmission 1.0) is see-through glass. A painted/anodised metallic blade (CS Doppler) is opaque β usegem-metal(metalness + gradient map + clearcoat, no transmission).
Procedural map generation (in code)
- CanvasTexture β draw to an
HTMLCanvasElement: linear/radial gradients across palette stops (gemstone/doppler), layered low-alpha blobs for smoke, per-pixel mottle noise for worn finishes, thin horizontal streaks for brushed metal.new THREE.CanvasTexture(canvas)then setcolorSpace. - DataTexture β push computed noise/height into a
Uint8Array,new THREE.DataTexture(arr,w,h, THREE.RGBAFormat, THREE.UnsignedByteType),colorSpace = NoColorSpace,needsUpdate = true. - Height β Normal (no native helper β compute it): Sobel/neighbour-difference the height field β
R = (dx*strength + 1)*0.5*255,G = (dy*strength + 1)*0.5*255,B = 255(up +Z), A = 255. - Independent channels (skill rule, confirmed): never alias one map into another β albedo, roughness, normal/height, AO are separate signals with separate frequency content.
Analysis β which finishClass?
analyze_texture.py classifies a reference crop by pure-stdlib stats:
- saturation + hue spread β chromatic gemstone vs neutral metal/grey.
- luminance gradient across the crop β
gradientfinish (doppler) vs flat. - local variance / mottle β
worn-composite. - directional (horizontal) high-freq streaks β
brushed-steel. - specular-highlight fraction (very bright pixels) β metalness proxy.
Output:
{finishClass, palette:[stops], mottle, gradientAxis, metalnessHint}β material recipe.