img2threejs / grimoire /build /threejs_texture_reference.md
Mike0021's picture
Add persistent community gallery and v1.3 previews
37e3d5a verified
|
Raw
History Blame Contribute Delete
3.76 kB

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), auto needsUpdate on construct.
  • DataTexture: flipY = false (default) β€” memory (0,0) is bottom-left. Set needsUpdate = true.
  • After changing wrapS/wrapT on an already-used texture you MUST set needsUpdate = true.
  • aoMap/lightMap read UV channel 1 β€” geometry needs a 2nd UV set, or set texture.channel = 1.
  • Tiling: wrapS = wrapT = THREE.RepeatWrapping + repeat.set(u,v); set anisotropy = 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 β€” use gem-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 set colorSpace.
  • 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 β†’ gradient finish (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.