# 機能設計書 63-ShaderMaterial

## 概要

本ドキュメントは、Three.jsライブラリにおけるカスタムシェーダー用マテリアル「ShaderMaterial」の機能設計について記述する。ShaderMaterialは、開発者が独自のGLSLシェーダーコードを記述し、Three.jsの組み込みシェーダーでは実現できない高度な視覚効果を実装するための基盤を提供する。

### 本機能の処理概要

ShaderMaterialは、カスタムの頂点シェーダーとフラグメントシェーダーを使用して、独自のレンダリング効果を実現するマテリアルクラスである。Three.jsの組み込みシェーダー機能（ライティング計算、フォグなど）をオプションで利用可能。

**業務上の目的・背景**：3Dグラフィックスの高度な表現において、組み込みマテリアルでは実現できない独自のビジュアルエフェクトが必要になることが多い。水面の屈折、ホログラム効果、プロシージャルテクスチャ、カスタムライティングモデル、ポストプロセッシングエフェクトなど、GPUプログラミング（シェーダー）を通じてのみ実現可能な表現がある。ShaderMaterialは、Three.jsの基盤を活用しながら、開発者がGLSLで独自のシェーダーを記述できる仕組みを提供し、無限の視覚的表現を可能にする。

**機能の利用シーン**：
- 水面、炎、煙などのプロシージャルエフェクト
- カスタムライティングモデル（NPR、トゥーンシェーディング拡張）
- ホログラム、ディストーション効果
- 頂点アニメーション（波、変形など）
- ポストプロセッシングエフェクト
- データビジュアライゼーション（ヒートマップ、グラデーション等）

**主要な処理内容**：
1. ユニフォーム変数の管理とGPUへの転送
2. カスタムGLSLシェーダーコード（vertex/fragment）の管理
3. definesによるプリプロセッサディレクティブの設定
4. Three.js組み込み機能（ライティング、フォグ、クリッピング）の統合オプション
5. WebGL拡張機能の有効化

**関連システム・外部連携**：WebGLRendererと連携してGPUへの描画命令を発行。WebGPURendererでは使用不可（TSLを推奨）。

**権限による制御**：特になし（クライアントサイドライブラリ）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Script Editor | 主機能 | カスタムシェーダーの編集 |

## 機能種別

データ定義 / カスタムシェーダー管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uniforms | Object | No | シェーダーユニフォーム変数（{name: {value: ...}}形式） | オブジェクト |
| uniformsGroups | Array | No | UBO用ユニフォームグループ配列 | UniformsGroup配列 |
| defines | Object | No | #defineディレクティブ用キー/値ペア | オブジェクト |
| vertexShader | string | No | 頂点シェーダーGLSLコード | 文字列 |
| fragmentShader | string | No | フラグメントシェーダーGLSLコード | 文字列 |
| linewidth | number | No | 線の太さ（デフォルト: 1） | 正の数値 |
| wireframe | boolean | No | ワイヤーフレーム表示（デフォルト: false） | boolean |
| wireframeLinewidth | number | No | ワイヤーフレーム線幅（デフォルト: 1） | 正の数値 |
| fog | boolean | No | フォグユニフォーム有効化（デフォルト: false） | boolean |
| lights | boolean | No | ライティングユニフォーム有効化（デフォルト: false） | boolean |
| clipping | boolean | No | クリッピングプレーンサポート（デフォルト: false） | boolean |
| extensions | Object | No | WebGL拡張設定 | オブジェクト |
| glslVersion | string | No | GLSLバージョン（GLSL1/GLSL3） | GLSL1/GLSL3/null |

### 入力データソース

コンストラクタのparametersオブジェクトから入力。シェーダーコードは文字列として直接、または<script>タグから取得。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isShaderMaterial | boolean | 型判定用フラグ（常にtrue） |
| type | string | マテリアルタイプ識別子（'ShaderMaterial'） |
| uniforms | Object | ユニフォーム変数オブジェクト |
| uniformsGroups | Array | UBOグループ配列 |
| defines | Object | プリプロセッサディレクティブ |
| vertexShader | string | 頂点シェーダーコード |
| fragmentShader | string | フラグメントシェーダーコード |
| linewidth | number | 線の太さ |
| wireframe | boolean | ワイヤーフレームフラグ |
| fog | boolean | フォグ有効フラグ |
| lights | boolean | ライティング有効フラグ |
| clipping | boolean | クリッピング有効フラグ |
| extensions | Object | 拡張設定 |
| glslVersion | string/null | GLSLバージョン |
| uniformsNeedUpdate | boolean | ユニフォーム更新フラグ |

### 出力先

WebGLRendererに描画パラメータとシェーダーコードとして提供される。

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ Material基底クラスのコンストラクタ実行
2. デフォルトプロパティの初期化
   └─ uniforms, defines, vertexShader, fragmentShader, etc.
3. デフォルトシェーダーの設定
   └─ default_vertex, default_fragment がデフォルト値
4. setValues(parameters)でパラメータ適用
5. レンダリング時の処理:
   a. WebGLRendererがシェーダーをコンパイル
   b. uniformsの値がGPUに転送
   c. メッシュがカスタムシェーダーで描画
```

### フローチャート

```mermaid
flowchart TD
    A[new ShaderMaterial] --> B[super - Material初期化]
    B --> C[デフォルト値設定]
    C --> D[デフォルトシェーダー設定]
    D --> E{parameters存在?}
    E -->|Yes| F[setValues実行]
    E -->|No| G[初期化完了]
    F --> G
    G --> H[レンダラーに提供]
    H --> I[シェーダーコンパイル]
    I --> J[ユニフォーム転送]
    J --> K[GPUで描画実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-63-1 | WebGL専用 | ShaderMaterialはWebGLRendererでのみ使用可能 | 常時 |
| BR-63-2 | 組み込み属性/ユニフォーム | Three.jsの組み込み属性・ユニフォームが自動的にシェーダーに追加される | 常時 |
| BR-63-3 | フォグユニフォーム | fog=trueの場合、フォグ関連ユニフォームをマージする必要がある | fog有効時 |
| BR-63-4 | ライティングユニフォーム | lights=trueの場合、ライト関連ユニフォームが渡される | lights有効時 |
| BR-63-5 | ループアンロール | #pragma unroll_loop_start/endでforループをアンロール可能 | 対応形式のループ |
| BR-63-6 | 線幅制限 | linewidth/wireframeLinewidthはWebGL/WebGPUで常に1px | 常時 |

### 計算ロジック

ユニフォームは毎フレーム更新され、GPUに転送される:
```javascript
// ユニフォーム値の更新例
material.uniforms.time.value = performance.now() * 0.001;
```

## データベース操作仕様

該当なし（クライアントサイドライブラリ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| GL_COMPILE_ERROR | シェーダーコンパイルエラー | GLSLシンタックスエラー | コンソールにエラーログ出力 |
| GL_LINK_ERROR | シェーダーリンクエラー | vertex/fragmentシェーダー間の不整合 | コンソールにエラーログ出力 |
| - | 警告 | 未定義のパラメータを渡した場合 | コンソールに警告を出力 |

### リトライ仕様

該当なし（コンパイルエラーは開発者が修正する必要がある）

## トランザクション仕様

該当なし

## パフォーマンス要件

- シェーダーコンパイルは初回レンダリング時に実行（初回描画遅延の原因）
- ユニフォーム更新は毎フレーム実行可能
- uniformsNeedUpdate=trueで強制更新
- 複雑なシェーダーはGPU負荷増加

## セキュリティ考慮事項

- ユーザー入力をシェーダーコードに直接挿入しないこと
- シェーダーコードのサニタイズは行われない

## 備考

- WebGPURendererではTSL（Three.js Shading Language）を推奨
- RawShaderMaterialでは組み込み属性/ユニフォームが追加されない

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ShaderMaterialの構造と関連するクラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Material.js | `src/materials/Material.js` | 基底クラスのプロパティ |
| 1-2 | UniformsUtils.js | `src/renderers/shaders/UniformsUtils.js` | cloneUniforms, cloneUniformsGroupsの実装 |

**読解のコツ**: ユニフォームは`{name: {value: ...}}`形式のオブジェクトとして管理される。

#### Step 2: エントリーポイントを理解する

ShaderMaterialクラス自体の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ShaderMaterial.js | `src/materials/ShaderMaterial.js` | クラス全体（414行の実装） |

**主要処理フロー**:
1. **39-50行目**: コンストラクタ開始、isShaderMaterial設定
2. **65-83行目**: definesプロパティ（#defineディレクティブ）
3. **85-107行目**: uniformsプロパティ
4. **109-114行目**: uniformsGroupsプロパティ（UBO用）
5. **116-128行目**: vertexShader/fragmentShaderプロパティ
6. **130-158行目**: linewidth、wireframe関連
7. **160-179行目**: fogプロパティ（フォグユニフォーム制御）
8. **181-198行目**: lightsプロパティ（ライティングユニフォーム）
9. **190-198行目**: clippingプロパティ
10. **200-206行目**: forceSinglePassデフォルト値
11. **208-219行目**: extensionsプロパティ（WebGL拡張）
12. **221-236行目**: defaultAttributeValuesプロパティ
13. **254行目**: uniformsNeedUpdateフラグ
14. **262行目**: glslVersionプロパティ
15. **264-268行目**: setValues実行
16. **272-303行目**: copyメソッド
17. **305-398行目**: toJSONメソッド（シリアライズ）

#### Step 3: デフォルトシェーダーを確認する

デフォルトで設定されるシェーダーコードを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | default_vertex.glsl.js | `src/renderers/shaders/ShaderChunk/default_vertex.glsl.js` | デフォルト頂点シェーダー |
| 3-2 | default_fragment.glsl.js | `src/renderers/shaders/ShaderChunk/default_fragment.glsl.js` | デフォルトフラグメントシェーダー |

### プログラム呼び出し階層図

```
ShaderMaterial (継承: Material)
    │
    ├─ constructor(parameters)
    │      │
    │      ├─ super() → Material.constructor()
    │      │                 └─ EventDispatcher()
    │      │
    │      ├─ デフォルトシェーダー設定
    │      │       ├─ vertexShader = default_vertex
    │      │       └─ fragmentShader = default_fragment
    │      │
    │      └─ setValues(parameters)
    │               └─ Material.setValues()
    │
    ├─ copy(source)
    │      │
    │      ├─ super.copy(source)
    │      ├─ cloneUniforms(source.uniforms)
    │      └─ cloneUniformsGroups(source.uniformsGroups)
    │
    ├─ toJSON(meta)
    │      └─ ユニフォーム/シェーダーのシリアライズ
    │
    └─ [レンダリング時]
           │
           └─ WebGLRenderer
                   │
                   ├─ WebGLProgram (シェーダーコンパイル)
                   ├─ WebGLUniforms (ユニフォーム転送)
                   └─ GPU描画実行
```

### データフロー図

```
[入力]                              [処理]                         [出力]

parameters ─────────────────▶ ShaderMaterial.constructor()
{                                       │
  uniforms: {                           ├─ プロパティ初期化
    time: {value: 0},                   │
    color: {value: new Color()}         │
  },                                    │
  vertexShader: '...',                  │
  fragmentShader: '...'                 └─ setValues()
}                                                │
                                                 ▼
                                    マテリアルインスタンス
                                                 │
                        ┌────────────────────────┴────────────────────────┐
                        ▼                                                  ▼
              WebGLProgram                                      WebGLUniforms
            (シェーダーコンパイル)                              (ユニフォーム転送)
                        │                                                  │
                        └────────────────────────┬────────────────────────┘
                                                 ▼
                                         GPU シェーダー実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ShaderMaterial.js | `src/materials/ShaderMaterial.js` | ソース | ShaderMaterialクラス定義 |
| Material.js | `src/materials/Material.js` | ソース | 基底マテリアルクラス |
| UniformsUtils.js | `src/renderers/shaders/UniformsUtils.js` | ソース | ユニフォームユーティリティ |
| UniformsLib.js | `src/renderers/shaders/UniformsLib.js` | ソース | 組み込みユニフォーム定義 |
| default_vertex.glsl.js | `src/renderers/shaders/ShaderChunk/default_vertex.glsl.js` | シェーダー | デフォルト頂点シェーダー |
| default_fragment.glsl.js | `src/renderers/shaders/ShaderChunk/default_fragment.glsl.js` | シェーダー | デフォルトフラグメントシェーダー |
| WebGLProgram.js | `src/renderers/webgl/WebGLProgram.js` | ソース | シェーダーコンパイル |
| WebGLUniforms.js | `src/renderers/webgl/WebGLUniforms.js` | ソース | ユニフォーム管理 |
