ShaderMaterial


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()vertexShaderfragmentShader プロパティとして渡します。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.valueperformance.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では attributeuniform mat4 の宣言は不要ですが、RawShaderMaterialではすべて明示的に書く必要があります。

まとめ

  • ShaderMaterialで頂点・フラグメントシェーダーを自由に定義できる
  • varying変数で頂点からフラグメントへデータを渡す
  • uniformsオブジェクトでJavaScriptからシェーダーにデータを送る
  • Three.jsがposition, uv, normal, 各種行列を自動提供する