title: "ShaderMaterial" description: "Three.jsのShaderMaterialを使ってカスタムシェーダーをメッシュに適用する方法を学びます。" chapter: "10-threejs" order: 1 challenge: description: "ShaderMaterialのuniformにu_colorを追加し、外部から色を制御できるようにしてください。u_colorの値(vec3)をベースにしたグラデーションを作りましょう。" hints:
- "uniformsオブジェクトにu_colorを追加します。値はTHREE.Vector3で指定します。"
- "フラグメントシェーダーで uniform vec3 u_color; を宣言し、色の計算に使います。"
- "ベースカラーにsin関数を掛け合わせて時間変化するグラデーションにしましょう。"
ShaderMaterial
Three.jsのシェーダーシステム
これまでフラグメントシェーダーだけで2D描画をしてきましたが、Three.jsを使うと3Dオブジェクトにカスタムシェーダーを適用できます。
Three.jsのShaderMaterialは、頂点シェーダーとフラグメントシェーダーの両方を自分で指定できるマテリアルです。
基本的な使い方
ShaderMaterialの基本構造はこのようになります:
// === 頂点シェーダー ===
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// === フラグメントシェーダー ===
uniform float u_time;
varying vec2 vUv;
void main() {
vec3 color = 0.5 + 0.5 * cos(u_time + vUv.xyx + vec3(0, 2, 4));
gl_FragColor = vec4(color, 1.0);
}
JavaScriptではこれらのシェーダー文字列を new THREE.ShaderMaterial() に vertexShader と fragmentShader プロパティとして渡します。uniforms プロパティでシェーダーに渡す値を定義します。
重要な組み込み変数
Three.jsのShaderMaterialでは、以下の変数が自動的に利用可能です:
頂点シェーダーで使える変数:
position-- 頂点の位置 (vec3)normal-- 頂点の法線 (vec3)uv-- テクスチャ座標 (vec2)modelViewMatrix-- モデルビュー行列 (mat4)projectionMatrix-- プロジェクション行列 (mat4)normalMatrix-- 法線行列 (mat3)
varying変数 で頂点シェーダーからフラグメントシェーダーにデータを渡します:
// 頂点シェーダー
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// フラグメントシェーダー
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv, 0.0, 1.0);
}
Uniformの受け渡し
JavaScriptからシェーダーにデータを渡すには uniforms オブジェクトを使います。各uniformは value プロパティを持つオブジェクトとして定義します:
u_time: value 0.0-- float型u_color: value new THREE.Vector3(1.0, 0.5, 0.2)-- vec3型u_intensity: value 1.0-- float型
アニメーションループ内で material.uniforms.u_time.value に performance.now() / 1000 を代入することで、時間の経過をシェーダーに反映できます。
RawShaderMaterial
RawShaderMaterialを使うと、Three.jsが自動追加するprecision宣言やビルトイン変数の定義が含まれません。すべてを自分で宣言する必要がありますが、シェーダーの動作を完全に制御できます:
// RawShaderMaterialの頂点シェーダー
precision highp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
通常のShaderMaterialでは attribute や uniform mat4 の宣言は不要ですが、RawShaderMaterialではすべて明示的に書く必要があります。
まとめ
ShaderMaterialで頂点・フラグメントシェーダーを自由に定義できるvarying変数で頂点からフラグメントへデータを渡すuniformsオブジェクトでJavaScriptからシェーダーにデータを送る- Three.jsが
position,uv,normal, 各種行列を自動提供する