mcpField
T
threejs-syntax-materials

threejs-syntax-materials

github.com/impertio-studioDevelopment23137 installsUpdated 30w ago
Repository

About threejs-syntax-materials

A Three.js reference skill for choosing and configuring materials and textures. It covers material types, color-space rules, lifecycle methods, and common pitfalls for 3D developers.

Key features

  1. 01Material selection by rendering use
  2. 02Common material properties and methods
  3. 03PBR and advanced material guidance
  4. 04Texture color-space and wrapping rules
  5. 05Shader updates and GPU cleanup advice

Use cases

  1. 01Choosing a material for a scene object
  2. 02Setting texture color spaces correctly
  3. 03Avoiding GPU leaks when removing objects

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/impertio-studio/three.js-claude-skill-package --skill threejs-syntax-materials

After installing, type/threejs-syntax-materialsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

.gitkeep
references/
anti-patterns.md
examples.md
methods.md

Details

From the project README

threejs-syntax-materials

Quick Reference

Material Type Decision Tree
Use CaseMaterialWhy
UI elements, unlit scenesMeshBasicMaterialCheapest, no light computation
Matte diffuse (low-end devices)MeshLambertMaterialFast diffuse, no specular
Legacy specular highlightsMeshPhongMaterialBlinn-Phong model, not physically correct
General-purpose 3D (recommended)MeshStandardMaterialPBR metalness/roughness, industry standard
Glass, car paint, fabric, soap bubblesMeshPhysicalMaterialAdvanced PBR (clearcoat, transmission, sheen, iridescence)
Cartoon/anime styleMeshToonMaterialDiscrete cel-shading steps
Sculpting previews, no lightsMeshMatcapMaterialMatcap texture, zero light setup
Debug normalsMeshNormalMaterialRGB = surface normal direction
Invisible shadow receiverShadowMaterialTransparent shadow catcher
Solid linesLineBasicMaterialSimple colored lines
Dashed linesLineDashedMaterialRequires line.computeLineDistances()
ParticlesPointsMaterialPoint cloud rendering
BillboardsSpriteMaterialAlways-facing-camera quads
Base Material Properties (All Materials)
PropertyTypeDefaultDescription
sidenumberFrontSideFrontSide, BackSide, or DoubleSide
transparentbooleanfalseEnable alpha blending
opacitynumber1Requires transparent: true to take effect below 1
depthWritebooleantrueWrite to depth buffer
depthTestbooleantrueTest against depth buffer
blendingnumberNormalBlendingNoBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
alphaTestnumber0Discard fragments with alpha below this value
visiblebooleantrueWhether to render this material
wireframebooleanfalseWireframe rendering mode
fogbooleantrueAffected by scene fog
clippingPlanesPlane[]nullArray of clipping planes
clipIntersectionbooleanfalseClip where ALL planes intersect (vs union)
needsUpdatebooleanfalseSet true to trigger shader recompilation
toneMappedbooleantrueApply renderer tone mapping
Base Material Methods
MethodSignatureDescription
clone(): MaterialClone the material
copy(source: Material): MaterialCopy properties from source
dispose(): voidFree GPU resources -- ALWAYS call when removing
onBeforeCompile(shader, renderer): voidHook to modify shader before compilation
setValues(values: Object): voidSet multiple properties at once
Critical Warnings

NEVER set opacity < 1 without transparent: true -- the opacity value is silently ignored. ALWAYS pair them together.

NEVER use MeshPhysicalMaterial when MeshStandardMaterial suffices -- Physical compiles a significantly larger shader. ONLY use it when you need clearcoat, transmission, sheen, iridescence, or anisotropy.

NEVER set SRGBColorSpace on normal maps, roughness maps, metalness maps, or any data texture -- this corrupts the data and causes incorrect lighting. ONLY set SRGBColorSpace on diffuse/color/emissive textures.

NEVER forget to call material.dispose() and texture.dispose() when removing objects -- GPU memory leaks accumulate and crash the application.

NEVER set linewidth > 1 on LineBasicMaterial -- it is silently ignored on most platforms due to WebGL limitations. ALWAYS use Line2 + LineMaterial from three/addons/lines/ for thick lines.

ALWAYS set material.needsUpdate = true after changing properties that affect shader compilation (e.g., toggling flatShading, changing side, adding/removing texture maps at runtime).

ALWAYS set wrapS and wrapT to RepeatWrapping when using texture.repeat values other than (1, 1) -- the default ClampToEdgeWrapping does NOT tile textures.


MeshStandardMaterial (PBR)

The recommended material for most 3D scenes. Uses physically-based metalness/roughness workflow.

import { MeshStandardMaterial, TextureLoader, SRGBColorSpace, RepeatWrapping } from 'three';

const loader = new TextureLoader();
const material = new MeshStandardMaterial({
  color: 0xffffff,
  roughness: 0.7,           // 0 = mirror, 1 = fully rough
  metalness: 0.0,           // 0 = dielectric, 1 = metal
  map: null,                // Diffuse/albedo texture
  roughnessMap: null,       // Per-pixel roughness
  metalnessMap: null,       // Per-pixel metalness
  normalMap: null,          // Surface normal perturbation
  normalScale: new Vector2(1, 1),
  aoMap: null,              // Ambient occlusion (requires uv2)
  aoMapIntensity: 1.0,
  emissive: 0x000000,       // Emissive color
  emissiveMap: null,        // Emissive texture
  emissiveIntensity: 1.0,
  envMap: null,             // Environment reflection map
  envMapIntensity: 1.0,
  bumpMap: null,            // Grayscale height map
  bumpScale: 1.0,
  displacementMap: null,    // Vertex displacement map
  displacementScale: 1.0,
  displacementBias: 0.0,
  alphaMap: null,           // Per-pixel transparency
  lightMap: null,           // Baked lighting (requires uv2)
  lightMapIntensity: 1.0,
  flatShading: false,
  wireframe: false,
  fog: true
});

MeshPhysicalMaterial (Advanced PBR)

Extends MeshStandardMaterial with ALL its properties, plus:

PropertyTypeDefaultDescription
clearcoatfloat0.0Clear coat layer intensity (0-1)
clearcoatRoughnessfloat0.0Clear coat roughness
clearcoatMapTexturenullClear coat intensity map
clearcoatNormalMapTexturenullClear coat normal map
transmissionfloat0.0Physically-based transparency (0-1)
transmissionMapTexturenullTransmission map
thicknessfloat0.0Volume thickness for transmission
thicknessMapTexturenullThickness map
iorfloat1.5Index of refraction (1.0-2.333)
attenuationDistancefloatInfinityLight attenuation distance in volume
attenuationColorColorwhiteLight attenuation tint
sheenfloat0.0Sheen layer intensity (fabric-like)
sheenColorColor0x000000Sheen tint color
sheenRoughnessfloat1.0Sheen roughness
iridescencefloat0.0Thin-film interference (0-1)
iridescenceIORfloat1.3Iridescence index of refraction
iridescenceThicknessRange[float, float][100, 400]Thin-film thickness range (nm)
anisotropyfloat0.0Anisotropic reflection strength
anisotropyRotationfloat0.0Anisotropy rotation (radians)
specularIntensityfloat1.0Specular layer intensity
specularColorColorwhiteSpecular tint color
dispersionfloat0.0Chromatic dispersion (rainbow effect)
reflectivityfloat0.5Reflectivity at normal incidence

Texture System

Color Space Rules (Critical)
Map TypeColor SpaceChannels Used
map (diffuse/albedo)SRGBColorSpaceRGB(A)
emissiveMapSRGBColorSpaceRGB
lightMapSRGBColorSpaceRGB
envMapSRGBColorSpaceRGB
sheenColorMapSRGBColorSpaceRGB
specularColorMapSRGBColorSpaceRGB
normalMapNoColorSpaceRGB
roughnessMapNoColorSpaceG channel
metalnessMapNoColorSpaceB channel
aoMapNoColorSpaceR channel
bumpMapNoColorSpaceR channel
displacementMapNoColorSpaceR channel
alphaMapNoColorSpaceR channel
clearcoatMapNoColorSpaceR channel
clearcoatRoughnessMapNoColorSpaceR channel
clearcoatNormalMapNoColorSpaceRGB
transmissionMapNoColorSpaceR channel
thicknessMapNoColorSpaceR channel
iridescenceMapNoColorSpaceR channel
iridescenceThicknessMapNoColorSpaceR channel
sheenRoughnessMapNoColorSpaceR channel
anisotropyMapNoColorSpaceRG channels
specularIntensityMapNoColorSpaceA channel

Rule: Diffuse/emissive/color textures = SRGBColorSpace. ALL data textures = NoColorSpace. Getting this wrong causes washed-out or over-saturated rendering.

Texture Loaders
LoaderFormatImport
TextureLoaderPNG, JPG, WebPthree core
CubeTextureLoader6x PNG/JPG cube mapsthree core
RGBELoader.hdr (Radiance HDR)three/addons/loaders/RGBELoader.js
EXRLoader.exr (OpenEXR HDR)three/addons/loaders/EXRLoader.js
KTX2Loader.ktx2 (GPU compressed)three/addons/loaders/KTX2Loader.js
Wrapping Modes
ConstantDescription
ClampToEdgeWrappingEdge texels stretched (default)
RepeatWrappingTexture tiles/repeats
MirroredRepeatWrappingTiles with alternating mirror
Filter Modes
ConstantTypeDescription
NearestFilterMag/MinPixelated, crisp (retro, toon gradients)
LinearFilterMag/MinSmooth interpolation
LinearMipmapLinearFilterMinTrilinear filtering (default, best quality)
Texture Properties
PropertyTypeDefaultDescription
wrapS / wrapTnumberClampToEdgeWrappingWrapping mode
magFilternumberLinearFilterMagnification filter
minFilternumberLinearMipmapLinearFilterMinification filter
anisotropynumber1Anisotropic filtering (max = renderer.capabilities.getMaxAnisotropy())
repeatVector2(1, 1)UV repeat count
offsetVector2(0, 0)UV offset
rotationnumber0UV rotation in radians
centerVector2(0, 0)Center of rotation
flipYbooleantrueFlip vertically on upload
colorSpacestringNoColorSpaceColor space interpretation
generateMipmapsbooleantrueAuto-generate mipmaps
needsUpdatebooleanfalseTrigger GPU re-upload
flipY Rules
  • flipY = true (default): Correct for loaded image textures (PNG, JPG)
  • flipY = false: ALWAYS use for WebGLRenderTarget textures, DataTexture, and framebuffer textures

Material Disposal

// ALWAYS dispose materials and textures when removing objects
function disposeMesh(mesh) {
  if (mesh.material) {
    // Dispose all texture maps
    for (const key of Object.keys(mesh.material)) {
      const value = mesh.material[key];
      if (value && value.isTexture) {
        value.dispose();
      }
    }
    mesh.material.dispose();
  }
  if (mesh.geometry) {
    mesh.geometry.dispose();
  }
}

needsUpdate Flag

ALWAYS set material.needsUpdate = true after changing these at runtime:

  • Toggling flatShading
  • Changing side (FrontSide/BackSide/DoubleSide)
  • Adding or removing a texture map (e.g., setting map from null to a texture)
  • Changing transparent or alphaTest
  • Toggling wireframe
  • Any property that changes the compiled shader variant

NEVER set needsUpdate = true every frame -- it forces expensive shader recompilation. ONLY set it once after the property change.

For textures: set texture.needsUpdate = true after modifying texture.image data to trigger GPU re-upload.


Toon Material Special Rule

When using MeshToonMaterial, ALWAYS set gradientMap.minFilter = NearestFilter and gradientMap.magFilter = NearestFilter. Linear filtering blurs the discrete shading steps into smooth gradients, defeating the toon effect.


Reference Links

Official Sources

Comments

Markdown supported