threejs-syntax-shaders について
threejs-syntax-shaders は、Three.js 開発者向けのシェーダーリファレンススキルです。マテリアル、GLSL 構文、カスタムシェーダーの作成やデバッグで起きやすい問題を扱います。
主な機能
- 01ShaderMaterial と RawShaderMaterial の比較
- 02uniform の型と値の形式の解説
- 03ShaderChunk と onBeforeCompile の説明
- 04GLSL3 構文と define 更新の解説
- 05シェーダーのコンパイルエラーの注意点
活用シーン
- 01Three.js のカスタムマテリアルシェーダーの作成
- 02外部 GLSL シェーダーの Three.js への移植
- 03uniform や GLSL のコンパイル問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-syntax-shadersインストール後、Claude Code で/threejs-syntax-shadersを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mdexamples.mdmethods.md詳細
threejs-syntax-shaders
クイックリファレンス
ShaderMaterial と RawShaderMaterial の比較
| 項目 | ShaderMaterial | RawShaderMaterial |
|---|---|---|
| 組み込みユニフォーム | 自動的に挿入されます | なし -- すべて自分で宣言する必要があります |
| 組み込み属性 | 自動的に宣言されます | なし -- すべて自分で宣言する必要があります |
#include <chunk> | 対応しています | 対応していません |
| 精度宣言 | 自動です | precision mediump float; を追加する必要があります |
| 用途 | Three.js のレンダリングを拡張する | シェーダーを完全に制御する、外部シェーダーを移植する |
| パフォーマンス | 未使用の組み込み要素によるわずかなオーバーヘッド | シェーダーのオーバーヘッドは最小限 |
ユニフォーム型の対応表
| GLSL 型 | JavaScript の値 |
|---|---|
float | { value: 1.0 } |
int | { value: 1 } |
bool | { value: true } |
vec2 | { value: new THREE.Vector2() } |
vec3 | { value: new THREE.Vector3() } または { value: new THREE.Color() } |
vec4 | { value: new THREE.Vector4() } |
mat3 | { value: new THREE.Matrix3() } |
mat4 | { value: new THREE.Matrix4() } |
sampler2D | { value: texture }(THREE.Texture インスタンス) |
samplerCube | { value: cubeTexture } |
float[] | { value: [1.0, 2.0, 3.0] } |
vec3[] | { value: [new THREE.Vector3(), ...] } |
重要な警告
ユニフォームに値をそのまま絶対に渡さないでください。必ず { value: ... } でラップしてください。uniforms: { uTime: 0.0 } と記述してもエラーなく失敗します。必ず uniforms: { uTime: { value: 0.0 } } と記述してください。
ShaderMaterial のシェーダーでは、組み込みユニフォームや属性を絶対に宣言しないでください。Three.js が自動的に挿入します。再宣言すると GLSL のコンパイルエラーが発生します。
RawShaderMaterial のシェーダーでは、すべてのユニフォーム、属性、精度を必ず宣言してください。何も自動挿入されません。
glslVersion が THREE.GLSL3 の場合、gl_FragColor や texture2D() は絶対に使用しないでください。代わりに、宣言した out vec4 変数と texture() を使用してください。
defines を変更した後は、必ず material.needsUpdate = true を設定してください。defines はシェーダーにコンパイルされるため、変更するには再コンパイルが必要です。
ShaderMaterial
コンストラクター
import * as THREE from 'three';
const material = new THREE.ShaderMaterial({
uniforms: {
uTime: { value: 0.0 },
uColor: { value: new THREE.Color(0x00ff00) },
uTexture: { value: someTexture },
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float uTime;
uniform vec3 uColor;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(uColor * vUv.x, 1.0);
}
`,
transparent: false,
wireframe: false,
side: THREE.FrontSide,
});
プロパティ
| プロパティ | 型 | デフォルト | 説明 |
|---|---|---|---|
uniforms | Object | {} | { name: { value: ... } } 形式 |
uniformsGroups | Array | [] | ユニフォームバッファオブジェクト(UBO) |
vertexShader | string | -- | GLSL 頂点シェーダーのソース |
fragmentShader | string | -- | GLSL フラグメントシェーダーのソース |
defines | Object | {} | プリプロセッサの #define ディレクティブ |
extensions | Object | {} | 有効にする GLSL 拡張機能 |
wireframe | boolean | false | ワイヤーフレームレンダリング |
lights | boolean | false | ライトのユニフォームをシェーダーに渡す |
fog | boolean | false | フォグのユニフォームをシェーダーに渡す |
clipping | boolean | false | クリッピング平面を有効にする |
glslVersion | string | null | null | GLSL1 の場合は null、GLSL 3.0 ES の場合は THREE.GLSL3 |
defaultAttributeValues | Object | -- | 属性がない場合のフォールバック値 |
組み込みユニフォーム(ShaderMaterial のみ)
これらは自動的に挿入されます。自分で宣言してはいけません。
// Transform matrices
uniform mat4 modelMatrix; // Object -> World
uniform mat4 modelViewMatrix; // Object -> Camera
uniform mat4 projectionMatrix; // Camera -> Clip
uniform mat4 viewMatrix; // World -> Camera
uniform mat3 normalMatrix; // Transpose inverse of modelViewMatrix
// Camera
uniform vec3 cameraPosition; // Camera world position
// When lights: true
uniform vec3 ambientLightColor;
// Plus structured arrays for directional, point, spot, hemisphere lights
組み込み属性(ShaderMaterial のみ)
これらは自動的に挿入されます。自分で宣言してはいけません。
attribute vec3 position; // Vertex position
attribute vec3 normal; // Vertex normal
attribute vec2 uv; // Primary UV coordinates
attribute vec2 uv2; // Secondary UV (for aoMap, lightMap)
attribute vec4 tangent; // Tangent vector (if computeTangents was called)
attribute vec3 color; // Vertex color (if geometry has color attribute)
RawShaderMaterial
シェーダーソースを完全に制御する必要がある場合に使用します。何も自動挿入されません。
const material = new THREE.RawShaderMaterial({
uniforms: {
uModelViewMatrix: { value: new THREE.Matrix4() },
uProjectionMatrix: { value: new THREE.Matrix4() },
},
vertexShader: `
precision highp float;
attribute vec3 position;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main() {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
});
RawShaderMaterial では、両方のシェーダーの先頭に precision highp float;(または mediump)を必ず追加してください。精度宣言を省略すると、モバイル端末や一部のデスクトップ用ドライバーで GLSL のコンパイルエラーが発生します。
ShaderChunk -- Three.js のシェーダーコードの再利用
THREE.ShaderChunk には、すべての内部シェーダーフラグメントが含まれています。ShaderMaterial では #include <chunk_name> を使用してください(RawShaderMaterial では使用できません)。
共通チャンク
| チャンク | 目的 |
|---|---|
<common> | 共通定数と関数(PI、saturate など) |
<fog_pars_vertex> / <fog_vertex> | フォグ対応(頂点) |
<fog_pars_fragment> / <fog_fragment> | フォグ対応(フラグメント) |
<shadowmap_pars_vertex> / <shadowmap_vertex> | シャドウ対応(頂点) |
<shadowmap_pars_fragment> / <shadowmap_fragment> | シャドウ対応(フラグメント) |
<lights_pars_begin> | ライト構造体の宣言 |
<begin_vertex> | position から transformed 変数を初期化 |
<project_vertex> | modelViewMatrix と projectionMatrix を適用 |
<normal_fragment_begin> | 法線マッピングのセットアップ |
<color_pars_vertex> / <color_vertex> | 頂点カラー対応 |
プログラムからチャンクにアクセスする
// Read the source of any chunk
console.log(THREE.ShaderChunk.common);
console.log(THREE.ShaderChunk.fog_pars_vertex);
onBeforeCompile -- 組み込みマテリアルへのパッチ適用
既存のマテリアルのシェーダーをコンパイル時に変更します。これにより、PBR ライティング、シャドウ、およびすべての組み込み機能が維持されます。
const material = new THREE.MeshStandardMaterial({ color: 0xff0000 });
material.onBeforeCompile = (shader) => {
shader.uniforms.uTime = { value: 0.0 };
shader.vertexShader = shader.vertexShader.replace(
'#include <begin_vertex>',
`
#include <begin_vertex>
transformed.y += sin(transformed.x * 5.0 + uTime) * 0.5;
`
);
// Store reference for uniform updates
material.userData.shader = shader;
};
// ALWAYS override customProgramCacheKey when using onBeforeCompile
material.customProgramCacheKey = () => 'my-wavy-material';
// In animation loop
if (material.userData.shader) {
material.userData.shader.uniforms.uTime.value = clock.getElapsedTime();
}
onBeforeCompile を使用する場合は、必ず customProgramCacheKey() をオーバーライドしてください。そうしないと、Three.js がパッチ未適用のシェーダープログラムをキャッシュから再利用し、変更が気づかないうちに反映されなくなる場合があります。
uniform にアクセスする前に、material.userData.shader が存在することを必ず確認してください。シェーダーオブジェクトは初回レンダリング時に遅延生成され、material.needsUpdate = true にすると再作成される場合があります。
Defines -- プリプロセッサディレクティブ
const material = new THREE.ShaderMaterial({
defines: {
USE_FOG: '', // #define USE_FOG
MAX_LIGHTS: 4, // #define MAX_LIGHTS 4
EPSILON: '0.001', // #define EPSILON 0.001
},
// ...shaders
});
実行時に defines を変更する方法:
material.defines.MAX_LIGHTS = 8;
material.needsUpdate = true; // REQUIRED -- triggers recompilation
GLSL3 モード
const material = new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
vertexShader: `
in vec3 position; // 'attribute' becomes 'in'
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
out vec3 vPosition; // 'varying' becomes 'out'
void main() {
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision highp float;
in vec3 vPosition; // 'varying' becomes 'in'
out vec4 fragColor; // replaces gl_FragColor
void main() {
fragColor = vec4(vPosition * 0.5 + 0.5, 1.0);
}
`,
});
GLSL1 と GLSL3 の構文
| GLSL1 | GLSL3 | コンテキスト |
|---|---|---|
attribute | in | 頂点シェーダーの入力 |
varying(頂点) | out | 頂点シェーダーの出力 |
varying(フラグメント) | in | フラグメントシェーダーの入力 |
gl_FragColor | out vec4 を宣言 | フラグメントシェーダーの出力 |
texture2D() | texture() | テクスチャサンプリング |
textureCube() | texture() | キューブテクスチャのサンプリング |
uniform の更新パターン
// At creation
const material = new THREE.ShaderMaterial({
uniforms: {
uTime: { value: 0.0 },
uResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
uMouse: { value: new THREE.Vector2() },
},
vertexShader: '...',
fragmentShader: '...',
});
// In animation loop -- update the .value property directly
function animate() {
material.uniforms.uTime.value = performance.now() / 1000;
material.uniforms.uMouse.value.set(mouseX, mouseY);
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
uniform オブジェクト自体(例:material.uniforms.uTime = { value: 5 })を決して置き換えないでください。既存の .value プロパティを必ず変更してください。オブジェクトを置き換えると、内部参照が壊れます。
参考リンク
- references/methods.md -- API シグネチャの一覧
- references/examples.md -- 動作するコード例
- references/anti-patterns.md -- 避けるべき方法