Three.js マテリアル
ターゲットは three.js r186。例では WebGLRenderer を使用。WebGPU および TSL セクションでは WebGPURenderer を使用します。
ローカルオーバーライド(2026-11-10 に Claude がこの PC 用に追加。元のスキルには含まれません)。 アニメーションショートパイプライン (
<ROOT>\studio、mromidev/claude-animated-shorts 由来) は three 0.175 (r175) に固定されています。
- Remotion 4.0.290 + @react-three/fiber 9.1.2 + pmndrs postprocessing 6.37.2。three は固定してください: shade.ts/cardshade.ts は three シェーダーチャンクを文字列パッチします。そのパイプラインで作業する場合:
- r176 以降が必要な「よくある間違い」/APIアドバイス(HDRLoader、Timer、PCFSoftShadowMap の非推奨、setEffects、 RenderPipeline、outputBufferType、mesh.pivot、Capsule
height、TSL/WebGPU)は無視してください。r175 に API が存在するか最初に確認してください。- useFrame、Clock、Timer、デルタタイム、setAnimationLoop、または requestAnimationFrame でアニメーションさせないでください。Remotion は フレームごとにレンダリングします: すべての値を
useCurrentFrame()/ fps から導出してください(クリップの場合はmixer.setTime(frame / fps))。- ポストプロセスは pmndrs
postprocessingを使用し、three/addons EffectComposer は使用しないでください: OutputPass は追加しないでください(2回 sRGB エンコードされます)。- トゥーンカラー: トーンマッピングはコンポーザー内で NEUTRAL です。ACES のデフォルトと
tonemapping_fragmentによる色味に注意してください。- 他の three.js プロジェクトでは、以下に記載されている元の r186 ガイダンスがそのまま適用されます。
クイックスタート
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 マテリアル - ライト付きのリアルなサーフェスに適したデフォルトの選択肢
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)); // ライト付きマテリアルはライトがないと黒く表示されます
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);
マテリアルタイプの概要
| マテリアル | 使用例 | 照明 |
|---|---|---|
| MeshBasicMaterial | 非発光色、テクスチャ、ワイヤーフレーム | なし |
| MeshLambertMaterial | マットな拡散面 | 拡散 |
| MeshPhongMaterial | 光沢のあるプラスチック、安価な鏡面 | 拡散 + 鏡面 |
| MeshStandardMaterial | PBR メタル/ラフネスワークフロー | PBR |
| MeshPhysicalMaterial | PBR にクリアコート、透過、シアー、虹色効果を追加 | PBR |
| MeshToonMaterial | セルシェーディング | トゥーンステップ |
| MeshMatcapMaterial | マテリアルキャプチャテクスチャにベイクされたライトの見た目、ライト不要 | ベイク済み |
| ShadowMaterial | 受ける影のみを表示する透明なサーフェス | 影のみ |
| PointsMaterial | ポイントクラウド | なし |
| LineBasicMaterial / LineDashedMaterial | ライン | なし |
| ShaderMaterial / RawShaderMaterial | カスタム GLSL、WebGLRenderer のみ | カスタム |
色データテクスチャ(map、emissiveMap、specularMap、sheenColorMap、specularColorMap、LDR matcap、色として使用されるキャンバスまたはビデオ)は texture.colorSpace = THREE.SRGBColorSpace が必要です。そうしないと色が薄く表示されます。スカラーマップ(normal、bump、displacement、roughness、metalness、ao、alpha、toon gradientMap)はデフォルトのままにします。HDR ローダーは独自のカラースペースを設定します。
MeshBasicMaterial
照明計算なし。高速で、常に表示されます。reflectivity(0~1)と combine(THREE.MultiplyOperation、THREE.MixOperation、THREE.AddOperation)を備えた envMap をサポートします。specularMap(sRGB)は環境マップの寄与をマスクします。
const map = await new THREE.TextureLoader().loadAsync("color.jpg");
map.colorSpace = THREE.SRGBColorSpace;
const material = new THREE.MeshBasicMaterial({
color: 0xffffff, // マップと乗算
map,
transparent: true,
opacity: 0.5,
side: THREE.DoubleSide, // FrontSide(デフォルト)、BackSide、DoubleSide
fog: true, // シーンのフォグの影響を受ける
});
MeshLambertMaterial と MeshPhongMaterial
Lambert は拡散のみ。Phong は鏡面ハイライトを追加します。Standard が重すぎる場合の安価な代替手段です。
const lambert = new THREE.MeshLambertMaterial({
color: 0x00ff00,
emissive: 0x111111, // 自己発光色
emissiveIntensity: 1,
});
const phong = new THREE.MeshPhongMaterial({
color: 0x0000ff,
specular: 0x111111, // ハイライト色
shininess: 30, // 高いほどハイライトがシャープ
flatShading: false, // フラット vs スムーズな法線
});
どちらも map、emissiveMap、specularMap(sRGB。環境マップ反射、および Phong のハイライトをマスク)、normalMap、bumpMap、displacementMap、aoMap、envMap、envMapIntensity、envMapRotation をサポートします。
MeshStandardMaterial (PBR)
物理ベースのレンダリング。リアルな結果に推奨されます。
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 は赤、roughness は緑、metalness は青。スカラーはデフォルトのまま
const material = new THREE.MeshStandardMaterial({
color: 0xffffff, // マップと乗算
roughness: 1.0, // 0 = 鏡面、1 = 完全拡散。roughnessMap(緑)と乗算
metalness: 1.0, // 0 = 誘電体、1 = 金属。metalnessMap(青)と乗算されるため、マップを使用する場合は 1 のままにする
map,
roughnessMap: ormMap,
metalnessMap: ormMap,
normalMap: null, // サーフェスの詳細。normalScale(Vector2)でスケール
aoMap: ormMap, // アンビエントオクルージョン(赤)。aoMapIntensity で強度
displacementMap: null, // 頂点変位。displacementScale でスケール、displacementBias でオフセット
emissive: 0x000000,
emissiveIntensity: 1,
emissiveMap: null, // sRGB
envMap: null, // または scene.environment に依存(下記参照)
fog: true,
});
lightMap(lightMapIntensity 付き)は、aoMap がオクルージョンをベイクするのと同じように間接光をベイクします。HDR または EXR の lightMap は LinearSRGBColorSpace であり、ローダーが設定します。
UV チャンネル: aoMap と lightMap は選択したチャンネルを読み取ります
すべての UV マップテクスチャは、texture.channel で選択された属性をサンプリングします。0 は uv(デフォルト)、1 は uv1、2 は uv2、3 は uv3 を読み取ります。aoMap と lightMap は 2 番目の UV セットを必要としません。channel を変更しない限り uv をサンプリングします。GLTFLoader は TEXCOORD_1 を uv1 としてロードし、channel を自身で設定します。
const aoMap = await new THREE.TextureLoader().loadAsync("ao.jpg"); // スカラーはデフォルトのまま
const material = new THREE.MeshStandardMaterial({ aoMap }); // uv をサンプリング: 追加の属性は不要
// 別のアンラップ(ベイクされた AO またはライトマップ)の代替: ベイカーの u,v ペアを uv1 にコピーします
const bakedUv = new THREE.Float32BufferAttribute(mesh.geometry.attributes.position.count * 2, 2); // コピーするまでゼロ埋め
mesh.geometry.setAttribute("uv1", bakedUv); mesh.material = material;
aoMap.channel = 1; // このマテリアルは uv の代わりに uv1 をサンプリングするようになりました
MeshPhysicalMaterial (高度な PBR)
MeshStandardMaterial をレイヤーおよびボリューム機能で拡張します。これらのほとんどにテクスチャのバリエーションが存在します: clearcoatMap、clearcoatRoughnessMap、clearcoatNormalMap、transmissionMap、thicknessMap、iridescenceMap、iridescenceThicknessMap、sheenColorMap、sheenRoughnessMap、anisotropyMap、specularIntensityMap、specularColorMap。
const material = new THREE.MeshPhysicalMaterial({
// クリアコート(車の塗装、ラッカー)
clearcoat: 1.0, // 0 = なし、1 = フルコート
clearcoatRoughness: 0.1,
// 透過(ガラス、水)- 背後にある不透明なオブジェクトと scene.background を屈折させます
transmission: 1.0, // 0 = 不透明、1 = 完全透過
thickness: 0.5, // 屈折のためのボリュームの厚さ
attenuationDistance: 1, // ワールド単位。Infinity(デフォルト)= 吸収なし
attenuationColor: new THREE.Color(0xffaa66), // 白色光は attenuationDistance 後にこの色になります
ior: 1.5, // 屈折率、1~2.333
// シアー(ファブリック、ベルベット)
sheen: 1.0,
sheenColor: new THREE.Color(0xffffff),
sheenRoughness: 0.5,
// 虹色効果(シャボン玉、油膜)
iridescence: 1.0,
iridescenceIOR: 1.3,
iridescenceThicknessRange: [100, 400], // ナノメートル
// 異方性(ブラシメタル)。anisotropyRotation で方向
anisotropy: 1.0,
// 分散(プリズムガラス)。再帰反射性(道路標識、安全装備)
dispersion: 0.0,
retroreflectivity: 0.0,
// スペキュラオーバーライド: specularIntensity、specularColor(およびそのマップ)
});
ガラス - 滑らかな表面と背後に何かを配置した透過:
const glass = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1,
thickness: 0.5,
ior: 1.5,
});
// transmission は背後にある不透明なオブジェクトと背景を屈折させます。scene.environment がその反射を追加します
MeshToonMaterial
セルシェーディング。グラデーションマップは非カラーデータです。デフォルトのカラースペースを維持してください。
const steps = new Uint8Array([120, 200]); // 2 つのシェーディングステップ
const gradientMap = new THREE.DataTexture(steps, 2, 1, THREE.RedFormat);
gradientMap.minFilter = THREE.NearestFilter; // ハードステップ。LinearFilter はそれらをブレンドします
gradientMap.magFilter = THREE.NearestFilter;
gradientMap.needsUpdate = true;
const material = new THREE.MeshToonMaterial({ color: 0x00ff00, gradientMap });
MeshNormalMaterial と MeshDepthMaterial
// 法線を RGB としてエンコード - デバッグとフラットなイラスト的な見た目
const normals = new THREE.MeshNormalMaterial({ flatShading: false, wireframe: false });
// 深度をグレースケールとして(BasicDepthPacking、デフォルト)。RGBADepthPacking はシェーダーで読み戻すためにパックします
const depth = new THREE.MeshDepthMaterial();
PointsMaterial
ポイントクラウド用。size はピクセル単位。sizeAttenuation(デフォルト、パースペクティブカメラのみ)を使用すると、キャンバスの高さの半分が乗算され、ポイントのビュースペース深度で除算されます。
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, // 距離に応じてスケール
alphaTest: 0.5, // map または alphaMap を使用: このアルファ未満のフラグメントを破棄
});
const points = new THREE.Points(geometry, material);
scene.add(points);
LineBasicMaterial と LineDashedMaterial
WebGL と WebGPU は常にライン プリミティブを 1 ピクセル幅で描画します。linewidth、linecap、linejoin は SVGRenderer にのみ影響します。WebGLRenderer で太い線を使用するには、three/addons/lines/ の LineGeometry と LineMaterial を持つ Line2 を使用します(linewidth はピクセル単位)。LineMaterial は ShaderMaterial であるため、WebGPURenderer には three/addons/lines/webgpu/Line2.js の Line2 が必要です。これは Line2NodeMaterial を使用します。
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 }); // 常に 1 px
const dashed = new THREE.LineDashedMaterial({ color: 0xffffff, dashSize: 0.5, gapSize: 0.25 });
const line = new THREE.Line(geometry, dashed);
line.computeLineDistances(); // 必須。そうしないと線は実線で描画されます
scene.add(line);
ShaderMaterial (WebGLRenderer のみ)
three.js ユニフォームが自動的に注入されるカスタム GLSL。常に GLSL ES 3.00 としてコンパイルされます: texture()、textureLod()、dFdx が機能し、texture2D / gl_FragColor はエイリアスとして残ります。glslVersion は設定しないままにします。ShaderMaterial、RawShaderMaterial、および onBeforeCompile には WebGPURenderer のパスがありません。そこではノードマテリアルと TSL を使用します。
const timer = new THREE.Timer();
timer.connect(document); // タブが非表示のときに一時停止
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(); // 毎フレーム最初に、引数なし
material.uniforms.time.value = timer.getElapsed();
renderer.render(scene, camera);
}
シェーダー内で宣言済み: modelMatrix、modelViewMatrix、projectionMatrix、viewMatrix、normalMatrix、cameraPosition、および属性 position、normal、uv(さらに InstancedMesh の場合は instanceMatrix。自分で適用します: projectionMatrix * modelViewMatrix * instanceMatrix * vec4(pos, 1.0)、vertexColors の場合は color)。追加の UV セットと tangent は宣言されていません。自分で in vec2 uv1; を追加してください。
RawShaderMaterial (WebGLRenderer のみ)
宣言は先頭に追加されません(glslVersion からの #version、SHADER_TYPE と SHADER_NAME の define、および defines のみ)。ただし、レンダラーは projectionMatrix、modelViewMatrix、viewMatrix、normalMatrix、modelMatrix、cameraPosition を依然として設定します。これらをシェーダーで宣言し、uniforms に渡さないでください。同名のエントリはドローごとに上書きされるか(modelMatrix、modelViewMatrix、normalMatrix)、カメラの値を置き換えます(projectionMatrix、viewMatrix、cameraPosition)。
const material = new THREE.RawShaderMaterial({
glslVersion: THREE.GLSL3, // これがないとシェーダーは GLSL ES 1.00 になり、texture() がありません
vertexShader: `
precision highp float;
precision highp int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
in vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
uniform vec3 color;
out vec4 fragColor;
void main() {
fragColor = vec4(color, 1.0);
}
`,
uniforms: { color: { value: new THREE.Color(0xff0000) } },
});
WebGPU と TSL
RenderPipeline の後の WebGPURenderer(r174~r186)はレガシーパスを削除しました。TSL のみ。ShaderMaterial、RawShaderMaterial、および onBeforeCompile は機能しません。代わりに NodeMaterial を拡張するか、下位レベルの MeshBasicNodeMaterial、MeshStandardNodeMaterial、MeshPhysicalNodeMaterial などを使用してください。これらは new でインスタンス化され、node material のプロパティセットを受け入れます。
import { MeshPhysicalNodeMaterial } from "three/addons/materials/MeshPhysicalNodeMaterial.js";
const material = new MeshPhysicalNodeMaterial({
color: 0x00aaff,
roughness: 0.4,
metalness: 0.5,
clearcoat: 0.8,
});
Node material は TSL で構築されています。oneMinus()、add()、mix()、sin() など、任意の TSL 関数をプロパティに渡すことができます。
import { time, vec4 } from "three/tsl";
material.colorNode = vec4(1, 0, 0, 1); // 純粋な赤
material.opacityNode = time.sin().add(1).div(2); // 0 ~ 1 の範囲で点滅
material.transparent = true;
既存のマテリアルをコードで TSL に変換するには(例:スキルが通常 WebGL マテリアルを作成するが、renderer.isWebGPUBackend === true の場合に webgpu バリアントを作成する場合):
function webgpuMaterial(material) {
// 標準 NodeMaterial の構築関数を使用
const ctor = material.constructor;
let nodeCtor;
if (ctor === THREE.MeshStandardMaterial) nodeCtor = MeshStandardNodeMaterial;
else if (ctor === THREE.MeshPhysicalMaterial) nodeCtor = MeshPhysicalNodeMaterial;
else if (ctor === THREE.MeshBasicMaterial) nodeCtor = MeshBasicNodeMaterial;
else throw new Error("未サポートの material type: " + ctor.name);
return new nodeCtor().copy(material);
}
TSL は WebGLRenderer でも動作します。three/addons/materials/ パスを必要とせずに import { ... } from "three/tsl"; でインポートしてください。TSL のコード例は上記の WebGPU セクションのとおりです。
WebGPU の注意事項
- サイズ 1 のマテリアルを
renderer.initTexture()で初期化する必要はありません。これは自動的に処理されます。 material.onBeforeCompileを使用しないでください。使用しても効果はありません。代わりにmaterial.userData.shaderでカスタムシェーダーコードにアクセスします(読み取り専用)。- サポートされるプロパティは
definesを通じて渡す必要があります。自己定義のuniformsはサポートされていません。TSL のuniform()グループを使用してください。 updateBeforeRenderは WebGL と WebGPU の両方で動作します。- 実行時に
material.typeを変更することはできません。
共通プロパティとテクニック
透明度とブレンディング
const material = new THREE.MeshStandardMaterial({
transparent: true, // blender を有効にする
opacity: 0.5, // 最終的なアルファ = mapAlpha * opacity
alphaTest: 0.1, // このアルファ未満のフラグメントを破棄
depthWrite: true, // false: 深度バッファに書き込まない(半透明ソート用)
depthTest: true, // 深度テストを実行するかどうか
});
// 高度なブレンドモード
material.blending = THREE.AdditiveBlending; // 加算(発光効果)
// THREE.NormalBlending(デフォルト)、THREE.SubtractiveBlending、THREE.MultiplyBlending、THREE.CustomBlending
// CustomBlending では blendSrc、blendDst、blendEquation を設定します
material.blending = THREE.CustomBlending;
material.blendSrc = THREE.SrcAlphaFactor;
material.blendDst = THREE.OneMinusSrcAlphaFactor;
material.blendEquation = THREE.AddEquation;
ステンシル
ステンシルバッファを使用してマスクされた領域にレンダリングします。
// ステンシル値を書き込むマテリアル(例:ステンシルマスク)
const stencilWrite = new THREE.MeshBasicMaterial({
color: 0xffffff,
stencilWrite: true,
stencilRef: 1,
stencilFunc: THREE.AlwaysStencilFunc, // 常に書き込む
stencilZPass: THREE.ReplaceStencilOp, // ピクセルが Z テストに合格したら値を置き換える
});
// ステンシル値に基づいてレンダリングするマテリアル(例:ステンシルマスク内のコンテンツ)
const stencilContent = new THREE.MeshBasicMaterial({
color: 0xff0000,
stencilWrite: false, // 書き込まない
stencilRef: 1,
stencilFunc: THREE.EqualStencilFunc, // ref と等しい場合にのみレンダリング
stencilFail: THREE.KeepStencilOp, // 失敗した場合は何もしない
stencilZFail: THREE.KeepStencilOp,
stencilZPass: THREE.KeepStencilOp,
});
環境応答
scene.environment を PMREMGenerator によって生成されたテクスチャに設定すると、Standard、Physical、および Matcap マテリアルが自動的にそれを使用します。
const rgbeLoader = new THREE.RGBELoader();
rgbeLoader.loadAsync("environment.hdr").then((texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
const pmremGenerator = new THREE.PMREMGenerator(renderer);
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
scene.environment = envMap; // envMap を個別に設定する代わりにこれを使用
scene.background = envMap; // シーンの背景として設定(オプション)
pmremGenerator.dispose();
});
マテリアルごとに envMap を設定するか、scene.environment を使用すると、環境マッププロパティがマテリアルに設定されていない限り、すべての Standard/Physical マテリアルに環境マップが適用されます。
よくある間違い
- sRGB とリニアの混同: テクスチャのカラースペースが
SRGBColorSpaceに設定されていない。カラーデータテクスチャ(map、emissiveMap、specularMap、sheenColorMap、specularColorMap)は sRGB としてマークする必要があります。法線マップ、ラフネスマップ、メタルネスマップ、AO マップ、変位マップ、グラデーションマップはデフォルトのリニアのままにします。 - 間違ったテクスチャの割り当て: ORM マップを間違ったチャンネルに割り当てる(例:
aoMapをすべてのチャンネルに設定するのではなく、個別のテクスチャを作成する)。ORM マップは単一のテクスチャとして正しく解釈されます: ao = 赤チャンネル、roughness = 緑チャンネル、metalness = 青チャンネル。 - 透明マテリアルの深度バッファの問題: レンダリング順序が間違っている(半透明オブジェクトの深度書き込みが有効になっている)。深度書き込みを無効にし、適切なレンダリング順序を使用します。
- シェーダー Uniform の競合: ShaderMaterial で GLSL 内蔵変数(
projectionMatrixなど)と競合する uniform を定義する。それらをuniformsに含めないでください。常に宣言されます。 - RawShaderMaterial で glslVersion を忘れる: RawShaderMaterial はデフォルトで GLSL ES 1.00 であり、
texture()関数を使用できません。glslVersion: THREE.GLSL3を設定する必要があります。そうしないと、コンパイルエラーが発生します。 - MeshToonMaterial でグラデーションマップのフィルタリングを間違える: グラデーションマップで
NearestFilterではなくLinearFilterを使用すると、トゥーンステップがブレンドされます。セルシェーディングにはNearestFilterを使用します。
重要なノート
- このスキルは three.js r186 を対象としています。WebGPU セクションは r174~r186 の WebGPURenderer に適用されます。
- ローカルオーバーライド(上部ボックス)は、アニメーションショートパイプラインで、three が r175 に固定されている場合に注意してください。そのパイプラインで作業する場合は、上部の指示に従ってください。
- WebGLRenderer で TSL を使用するには、three.js r170+ が必要です。
- モバイルデバイスと省電力 GPU では、
MeshPhysicalMaterialの透過とクリアコートがレンダリングの問題を引き起こす可能性があります。