Three.js-Materialien
Zielplattform: three.js r186. Die Beispiele verwenden WebGLRenderer; der Abschnitt zu WebGPU und TSL verwendet WebGPURenderer.
Lokaler Override (hinzugefügt 2026-11-10 von Claude für diesen PC; kein Teil des ursprünglichen Skills). Unsere Animationskurzfilm-Pipeline (
<ROOT>\studio, von mromidev/claude-animated-shorts) ist auf three 0.175 (r175)
- Remotion 4.0.290 + @react-three/fiber 9.1.2 + pmndrs postprocessing 6.37.2 festgelegt. Halten Sie three fest: shade.ts/cardshade.ts patcht three-Shader-Chunks mit Strings. Wenn Sie an dieser Pipeline arbeiten:
- Ignorieren Sie "Häufige Fehler" / API-Hinweise, die r176+ erfordern (HDRLoader, Timer, PCFSoftShadowMap-Deprecation, setEffects, RenderPipeline, outputBufferType, mesh.pivot, Capsule
height, TSL/WebGPU). Überprüfen Sie zuerst, ob die API in r175 existiert.- Animieren Sie niemals mit useFrame, Clock, Timer, delta time, setAnimationLoop oder requestAnimationFrame. Remotion rendert Bild für Bild: Leiten Sie jeden Wert von
useCurrentFrame()/ fps ab (undmixer.setTime(frame / fps)für Clips).- Post-Processing verwendet pmndrs
postprocessing, nicht three/addons EffectComposer: Fügen Sie keinen OutputPass hinzu (doppelte sRGB-Kodierung).- Toon-Farben: Das Tone Mapping ist in unserem Composer NEUTRAL; achten Sie auf ACES-Standardwerte und
tonemapping_fragment-Tönung.- Für andere three.js-Projekte gilt die ursprüngliche r186-Anleitung unten wie geschrieben.
Schnellstart
import * as THREE from "three";
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 0, 3);
// PBR-Material – die Standardwahl für beleuchtete, realistische Oberflächen
const material = new THREE.MeshStandardMaterial({
color: 0x00aaff,
roughness: 0.35,
metalness: 0.1,
});
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 48, 32), material);
scene.add(mesh);
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 1)); // beleuchtete Materialien ohne Lichter schwarz rendern
const light = new THREE.DirectionalLight(0xffffff, 2);
light.position.set(3, 3, 3);
scene.add(light);
function animate() {
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
renderer.setAnimationLoop(animate);
Übersicht über Materialtypen
| Material | Anwendungsfall | Beleuchtung |
|---|---|---|
| MeshBasicMaterial | Unlit Farbe, Texturen, Drahtgitter | Keine |
| MeshLambertMaterial | Matte diffuse Oberflächen | Diffus |
| MeshPhongMaterial | Glänzendes Plastik, günstiger Glanz | Diffus + Glanz |
| MeshStandardMaterial | PBR Metall/Rauheits-Workflow | PBR |
| MeshPhysicalMaterial | PBR plus Klarlack, Transmission, Schimmer, Irisieren | PBR |
| MeshToonMaterial | Cel-Shading | Toon-Stufen |
| MeshMatcapMaterial | Beleuchteter Look in eine Matcap-Textur gebacken, keine Lichter benötigt | Gebacken |
| ShadowMaterial | Transparente Oberfläche, die nur die empfangenen Schatten zeigt | Nur Schatten |
| PointsMaterial | Punktwolken | Keine |
| LineBasicMaterial / LineDashedMaterial | Linien | Keine |
| ShaderMaterial / RawShaderMaterial | Benutzerdefiniertes GLSL, nur WebGLRenderer | Benutzerdefiniert |
Farb-Datentexturen (map, emissiveMap, specularMap, sheenColorMap, specularColorMap, LDR-Matcap, eine als Farbe verwendete Leinwand oder Video) benötigen texture.colorSpace = THREE.SRGBColorSpace, sonst werden Farben ausgewaschen dargestellt. Skalare Maps (normal, bump, displacement, roughness, metalness, ao, alpha, toon gradientMap) behalten die Standardeinstellung. HDR-Lader setzen ihren eigenen Farbraum.
MeshBasicMaterial
Keine Beleuchtungsberechnungen. Schnell, immer sichtbar. Unterstützt envMap mit reflectivity (0 bis 1) und combine (THREE.MultiplyOperation, THREE.MixOperation, THREE.AddOperation); specularMap (sRGB) maskiert den envMap-Beitrag.
const map = await new THREE.TextureLoader().loadAsync("color.jpg");
map.colorSpace = THREE.SRGBColorSpace;
const material = new THREE.MeshBasicMaterial({
color: 0xffffff, // mit der Map multipliziert
map,
transparent: true,
opacity: 0.5,
side: THREE.DoubleSide, // FrontSide (Standard), BackSide, DoubleSide
fog: true, // vom Szenen-Nebel beeinflusst
});
MeshLambertMaterial und MeshPhongMaterial
Lambert ist nur diffus. Phong fügt einen Glanzlichter-Highlight hinzu; es ist die günstige Alternative, wenn Standard zu schwer ist.
const lambert = new THREE.MeshLambertMaterial({
color: 0x00ff00,
emissive: 0x111111, // Eigenleuchtfarbe
emissiveIntensity: 1,
});
const phong = new THREE.MeshPhongMaterial({
color: 0x0000ff,
specular: 0x111111, // Highlight-Farbe
shininess: 30, // höher = schärferes Highlight
flatShading: false, // flache vs. glatte Normalen
});
Beide unterstützen auch map, emissiveMap, specularMap (sRGB; maskiert die envMap-Reflexion und bei Phong das Highlight), normalMap, bumpMap, displacementMap, aoMap, envMap, envMapIntensity und envMapRotation.
MeshStandardMaterial (PBR)
Physikalisch basiertes Rendering. Empfohlen für realistische Ergebnisse.
const map = await new THREE.TextureLoader().loadAsync("color.jpg");
map.colorSpace = THREE.SRGBColorSpace;
const ormMap = await new THREE.TextureLoader().loadAsync("orm.jpg"); // glTF ORM: ao rot, roughness grün, metalness blau; skalar: Standardwert beibehalten
const material = new THREE.MeshStandardMaterial({
color: 0xffffff, // mit der Map multipliziert
roughness: 1.0, // 0 = Spiegel, 1 = vollständig diffus; mit roughnessMap (grün) multipliziert
metalness: 1.0, // 0 = Dielektrikum, 1 = Metall; mit metalnessMap (blau) multipliziert, also bei einer Map auf 1 lassen
map,
roughnessMap: ormMap,
metalnessMap: ormMap,
normalMap: null, // Oberflächendetails; Skalierung mit normalScale (ein Vector2)
aoMap: ormMap, // Ambient Occlusion (rot); Intensität mit aoMapIntensity
displacementMap: null, // Vertex-Verschiebung; Skalierung mit displacementScale, Versatz mit displacementBias
emissive: 0x000000,
emissiveIntensity: 1,
emissiveMap: null, // sRGB
envMap: null, // oder auf scene.environment zurückgreifen (siehe unten)
fog: true,
});
lightMap (mit lightMapIntensity) backt indirektes Licht genauso wie aoMap Okklusion backt; eine HDR- oder EXR-lightMap ist LinearSRGBColorSpace, was die Lader festlegen.
UV-Kanäle: aoMap und lightMap lesen den von Ihnen gewählten Kanal
Jede UV-gemappte Textur samplet das Attribut, das durch texture.channel ausgewählt wird: 0 liest uv (der Standard), 1 liest uv1, 2 liest uv2, 3 liest uv3. aoMap und lightMap benötigen kein zweites UV-Set – sie samplen uv, es sei denn, Sie ändern channel. GLTFLoader lädt TEXCOORD_1 als uv1 und setzt channel selbst.
const aoMap = await new THREE.TextureLoader().loadAsync("ao.jpg"); // skalar: Standardwert beibehalten
const material = new THREE.MeshStandardMaterial({ aoMap }); // samplet uv: kein zusätzliches Attribut erforderlich
// Alternative für eine separate Entfaltung (eine gebackene AO- oder Lightmap): Kopieren Sie die u,v-Paare Ihres Bakers in uv1
const bakedUv = new THREE.Float32BufferAttribute(mesh.geometry.attributes.position.count * 2, 2); // mit Nullen gefüllt, bis Sie sie hineinkopieren
mesh.geometry.setAttribute("uv1", bakedUv); mesh.material = material;
aoMap.channel = 1; // dieses Material samplet jetzt uv1 statt uv
MeshPhysicalMaterial (Erweitertes PBR)
Erweitert MeshStandardMaterial um Layer- und Volumenfunktionen. Texturvarianten existieren für die meisten davon: clearcoatMap, clearcoatRoughnessMap, clearcoatNormalMap, transmissionMap, thicknessMap, iridescenceMap, iridescenceThicknessMap, sheenColorMap, sheenRoughnessMap, anisotropyMap, specularIntensityMap, specularColorMap.
const material = new THREE.MeshPhysicalMaterial({
// Klarlack (Autolack, Lack)
clearcoat: 1.0, // 0 = keiner, 1 = vollständige Beschichtung
clearcoatRoughness: 0.1,
// Transmission (Glas, Wasser) – bricht die dahinter liegenden undurchsichtigen Objekte und den Szenenhintergrund
transmission: 1.0, // 0 = undurchsichtig, 1 = vollständig durchlässig
thickness: 0.5, // Volumendicke für Brechung
attenuationDistance: 1, // Welteinheiten; Infinity (der Standard) = keine Absorption
attenuationColor: new THREE.Color(0xffaa66), // weißes Licht wird nach attenuationDistance zu dieser Farbe
ior: 1.5, // Brechungsindex, 1 bis 2,333
// Schimmer (Stoff, Samt)
sheen: 1.0,
sheenColor: new THREE.Color(0xffffff),
sheenRoughness: 0.5,
// Irisieren (Seifenblasen, Ölfilme)
iridescence: 1.0,
iridescenceIOR: 1.3,
iridescenceThicknessRange: [100, 400], // Nanometer
// Anisotropie (gebürstetes Metall); Richtung mit anisotropyRotation
anisotropy: 1.0,
// Dispersion (prismatisches Glas); Retroreflexion (Verkehrsschilder, Sicherheitsausrüstung)
dispersion: 0.0,
retroreflectivity: 0.0,
// Specular-Overrides: specularIntensity, specularColor (plus deren Maps)
});
Glas – Transmission mit einer glatten Oberfläche und etwas dahinter zum Brechen:
const glass = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1,
thickness: 0.5,
ior: 1.5,
});
// transmission bricht die undurchsichtigen Objekte und den Hintergrund dahinter; scene.environment fügt seine Reflexionen hinzu
MeshToonMaterial
Cel-Shading. Die Gradienten-Map ist Nicht-Farbdaten – behalten Sie ihren Standard-Farbraum bei.
const steps = new Uint8Array([120, 200]); // zwei Schattierungsstufen
const gradientMap = new THREE.DataTexture(steps, 2, 1, THREE.RedFormat);
gradientMap.minFilter = THREE.NearestFilter; // harte Stufen; LinearFilter vermischt sie
gradientMap.magFilter = THREE.NearestFilter;
gradientMap.needsUpdate = true;
const material = new THREE.MeshToonMaterial({ color: 0x00ff00, gradientMap });
MeshNormalMaterial und MeshDepthMaterial
// Normalen als RGB codiert – Debugging und flache illustrative Darstellungen
const normals = new THREE.MeshNormalMaterial({ flatShading: false, wireframe: false });
// Tiefe als Graustufen (BasicDepthPacking, der Standard); RGBADepthPacking packt es zum Auslesen in einem Shader
const depth = new THREE.MeshDepthMaterial();
PointsMaterial
Für Punktwolken. size ist in Pixeln; mit sizeAttenuation (Standard, nur perspektivische Kameras) wird es mit der halben Canvas-Höhe multipliziert und durch die Tiefe des Punktes im View-Raum geteilt.
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.Float32BufferAttribute([0, 0, 0, 1, 0.5, 0, 0.5, 1, 0], 3));
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
sizeAttenuation: true, // mit der Entfernung skalieren
alphaTest: 0.5, // mit einer map oder alphaMap: Fragmente unterhalb dieses Alphawerts verwerfen
});
const points = new THREE.Points(geometry, material);
scene.add(points);
LineBasicMaterial und LineDashedMaterial
WebGL und WebGPU zeichnen Linien-Primitive immer 1 px breit; linewidth, linecap und linejoin wirken sich nur auf den SVGRenderer aus. Für dicke Linien unter WebGLRenderer verwenden Sie Line2 mit LineGeometry und LineMaterial aus three/addons/lines/ (linewidth in Pixeln); LineMaterial ist ein ShaderMaterial, daher benötigt WebGPURenderer Line2 aus three/addons/lines/webgpu/Line2.js, welches Line2NodeMaterial verwendet.
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.Float32BufferAttribute([-1, 0, 0, 1, 0, 0], 3));
const solid = new THREE.LineBasicMaterial({ color: 0xffffff }); // immer 1 px
const dashed = new THREE.LineDashedMaterial({ color: 0xffffff, dashSize: 0.5, gapSize: 0.25 });
const line = new THREE.Line(geometry, dashed);
line.computeLineDistances(); // erforderlich, sonst wird die Linie durchgezogen gezeichnet
scene.add(line);
ShaderMaterial (nur WebGLRenderer)
Benutzerdefiniertes GLSL mit drei.js-Uniforms, die für Sie injiziert werden. Es wird immer als GLSL ES 3.00 kompiliert: texture(), textureLod() und dFdx funktionieren, und texture2D / gl_FragColor bleiben als Aliasse – lassen Sie glslVersion ungesetzt. ShaderMaterial, RawShaderMaterial und onBeforeCompile haben keinen WebGPURenderer-Pfad; verwenden Sie dort Node-Materialien und TSL.
const timer = new THREE.Timer();
timer.connect(document); // pausieren, wenn der Tab ausgeblendet ist
const material = new THREE.ShaderMaterial({
uniforms: { time: { value: 0 } },
vertexShader: `
varying vec2 vUv;
uniform float time;
void main() {
vUv = uv;
vec3 pos = position;
pos.z += sin(pos.x * 10.0 + time) * 0.1;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
varying vec2 vUv;
uniform float time;
void main() {
vec3 col = 0.5 + 0.5 * cos(time + vUv.xyx * 3.0);
gl_FragColor = vec4(col, 1.0);
}
`,
});
function animate() {
timer.update(); // als erstes jeden Frame, kein Argument
material.uniforms.time.value = timer.getElapsed();
renderer.render(scene, camera);
}
Für Sie im Shader deklariert: modelMatrix, modelViewMatrix, projectionMatrix, viewMatrix, normalMatrix, cameraPosition sowie die Attribute position, normal, uv (plus instanceMatrix bei einem InstancedMesh, das Sie selbst anwenden: projectionMatrix * modelViewMatrix * instanceMatrix * vec4(pos, 1.0), und color mit vertexColors). Die zusätzlichen UV-Sets und tangent werden nicht deklariert – fügen Sie in vec2 uv1; selbst hinzu.
RawShaderMaterial (nur WebGLRenderer)
Es werden keine Deklarationen vorangestellt (nur #version von glslVersion, die SHADER_TYPE- und SHADER_NAME-Defines sowie Ihre defines), aber der Renderer setzt trotzdem projectionMatrix, modelViewMatrix, viewMatrix, normalMatrix, modelMatrix und cameraPosition – deklarieren Sie sie im Shader und übergeben Sie sie niemals in uniforms: Ein gleichnamiger Eintrag wird bei jedem Draw überschrieben (modelMatrix, modelViewMatrix, normalMatrix) oder ersetzt den Wert der Kamera (projectionMatrix, viewMatrix, cameraPosition).
const material = new THREE.RawShaderMaterial({
glslVersion: THREE.GLSL3, // ohne dies ist der Shader GLSL ES 1.00, das kein texture() hat
vertexShader: `
precision highp float;
in vec3 position;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
out vec4 fragColor;
void main() {
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
});
Gemeinsame Eigenschaften
Textur-Farbräume
- Farbdaten (map, emissiveMap, specularMap, sheenColorMap, specularColorMap, Matcap, als Farbe verwendetes Video/Canvas):
texture.colorSpace = THREE.SRGBColorSpace - Skalare Daten (normal, bump, displacement, roughness, metalness, ao, alpha, gradientMap): Standard
THREE.LinearSRGBColorSpacebelassen - HDR-Daten (PMREMGenerator, EXRLoader, RGBELoader): Lader setzen
THREE.LinearSRGBColorSpace
side
THREE.FrontSide(Standard) – nur VorderseiteTHREE.BackSide– nur Rückseite (für Innenräume)THREE.DoubleSide– beide Seiten (teurer, für transparente Blätter)
transparent
Legt fest, ob opaker Inhalt durch transparente Bereiche hindurchscheint und in welcher Reihenfolge Fragmente zusammengesetzt werden. Mit alphaTest können Fragmente unterhalb eines Schwellenwerts verworfen werden.
blending
THREE.NormalBlending(Standard)THREE.AdditiveBlending– Farbe hinzufügen (Lichteffekte)THREE.SubtractiveBlending– Farbe abziehenTHREE.MultiplyBlending– Farbe multiplizierenTHREE.CustomBlending– mit benutzerdefinierten blendSrc, blendDst, blendEquation, blendSrcAlpha, blendDstAlpha, blendEquationAlpha
stencil
Materialien können über die Stencil-Puffer-Funktionen des Renderers schreiben und testen: stencilWrite, stencilRef, stencilFunc, stencilFail, stencilZFail, stencilZPass.
depthWrite / depthTest
depthWrite (Standard true) steuert, ob das Material in den Tiefenpuffer schreibt. depthTest testet gegen den Tiefenpuffer. Schalten Sie depthWrite aus für transparente Objekte, wenn die Sortierung nicht der einzige Grund für Artefakte ist.
polygonOffset
Verhindert Z-Fighting, wenn zwei Flächen auf derselben Ebene liegen: polygonOffset, polygonOffsetFactor, polygonOffsetUnits.
Umgebungsreaktion und Beleuchtung
scene.environment
Setzen Sie scene.environment = pmremGenerator.fromScene(...).texture für Standard-Environment-Maps (falls ein Mesh keine eigene envMap hat). MeshPhysicalMaterial respektiert dies ebenfalls.
const pmremGenerator = new THREE.PMREMGenerator(renderer);
const envMapTexture = pmremGenerator.fromScene(new THREE.RoomEnvironment()).texture;
scene.environment = envMapTexture;
const material = new THREE.MeshStandardMaterial(); // verwendet scene.environment
envMap am Material
Eine Material-eigene envMap überschreibt scene.environment:
material.envMap = envMapTexture; // verwendet diese statt scene.environment
material.envMapIntensity = 1.5; // Standard 1
material.envMapRotation = new THREE.Euler(0, Math.PI / 2, 0); // Drehung der envMap um y
Lichter
Beleuchtete Materialien (Lambert, Phong, Standard, Physical, Toon) benötigen Lichter in der Szene, sonst sind sie schwarz. Fügen Sie immer mindestens ein ambient oder hemisphere light hinzu:
// Sanftes Umgebungslicht
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 1));
scene.add(new THREE.DirectionalLight(0xffffff, 2));
WebGPU und TSL (WebGPURenderer)
Ab three.js r186 (r185+ experimentell) bietet TSL (Three Shading Language) eine Alternative zu ShaderMaterial und Node-Materialien. Hier gezeigt mit dem WebGPURenderer.
import { WebGPURenderer, PostProcessing } from "three/addons";
const renderer = new WebGPURenderer();
const context = renderer.getContext();
// Beispiel für ein benutzerdefiniertes Node-Material mit TSL
const material = new THREE.MeshStandardNodeMaterial();
material.colorNode = new THREE.Color(0x00aaff).toNode();
TSL-Dokumentation in Entwicklung; siehe r186-Änderungsprotokoll.
Häufige Fehler
- Farbraum nicht gesetzt:
map.colorSpacemussTHREE.SRGBColorSpacefür Farbdaten sein. - Lichter vergessen: Beleuchtete Materialien ohne Lichter ergeben Schwarz.
- ShaderMaterial nur WebGL: Verwenden Sie für WebGPU Node-Materialien oder TSL.
- linewidth: WebGL/WebGPU ignorieren
linewidth> 1; verwenden Sie Line2. - depthWrite bei Transparenz: Deaktivieren Sie
depthWritenicht standardmäßig; schalten Sie es nur bei Bedarf aus.