# 機能設計書 175-NodeManager

## 概要

本ドキュメントは、Three.jsのノードシステム管理クラス「NodeManager」の機能設計について記述する。NodeManagerはレンダラーとノードシステムの間のプライマリインターフェースとして、ノード関連オブジェクトの管理を行う。

### 本機能の処理概要

NodeManagerクラスは、Three.jsのノードベースレンダリングシステムにおいて中核的な役割を担う管理クラスである。レンダーオブジェクトに対するノードビルダーステートの生成・キャッシュ、シーンの環境・フォグ・背景のノード変換、ユニフォームグループの更新判定など、ノードシステムのライフサイクル全体を管理する。

**業務上の目的・背景**：ノードベースマテリアルシステムでは、シェーダーの生成・更新が頻繁に発生する。NodeManagerはこれらの処理を効率的に管理し、不要な再コンパイルを避けることでレンダリング性能を最適化する。また、シーンの環境マップやフォグなどの設定をノードベースの表現に自動変換することで、従来のマテリアルシステムとの互換性を維持する。

**機能の利用シーン**：
- WebGPURendererでのレンダリング時（内部的に使用）
- ノードベースマテリアルのシェーダー生成時
- シーンの環境マップ・フォグ・背景の処理時
- コンピュートシェーダーの実行時
- レンダーオブジェクトのキャッシュ管理時

**主要な処理内容**：
1. getForRender: レンダーオブジェクト用のノードビルダーステートを取得
2. getForCompute: コンピュートノード用のノードビルダーステートを取得
3. updateGroup: ユニフォームグループの更新判定
4. getEnvironmentNode/getFogNode/getBackgroundNode: シーンプロパティのノード変換
5. updateBefore/updateAfter/updateForRender: ノードのライフサイクル更新

**関連システム・外部連携**：
- WebGPURenderer: NodeManagerを内部的に使用
- NodeBuilderState: ビルドされたシェーダー情報を保持
- NodeFrame: フレームごとのノード更新を管理
- ChainMap: キャッシュキーの管理

**権限による制御**：特になし（内部APIとして使用）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | WebGPUサンプル | 補助機能 | ノードシステムの管理 |

## 機能種別

レンダリング管理 / キャッシュ管理 / ノードシステム

## 入力仕様

### 入力パラメータ

#### コンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| renderer | Renderer | Yes | レンダラーインスタンス | - |
| backend | Backend | Yes | バックエンドインスタンス | - |

#### getForRender メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| renderObject | RenderObject | Yes | レンダーオブジェクト | - |

#### getForCompute メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| computeNode | Node | Yes | コンピュートノード | - |

#### updateGroup メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodeUniformsGroup | NodeUniformsGroup | Yes | ユニフォームグループ | - |

### 入力データソース

- RenderObject: レンダリング対象のオブジェクト情報
- Scene: 環境、フォグ、背景の設定
- Node: コンピュートノード

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| NodeBuilderState | NodeBuilderState | ビルドされたシェーダー情報 |
| Node | Node | シーンプロパティのノード表現 |

### 出力先

- レンダラー内部のシェーダーパイプライン
- GPUシェーダープログラム

## 処理フロー

### 処理シーケンス

#### getForRender

```
1. レンダーオブジェクトのデータを取得
2. キャッシュにノードビルダーステートがあるか確認
3. キャッシュにない場合：
   └─ キャッシュキーを計算
   └─ キャッシュキーで既存のステートを検索
   └─ 見つからない場合：
       └─ NodeBuilderを作成
       └─ シーン、マテリアル、カメラ等を設定
       └─ 環境ノード、フォグノードを取得
       └─ build()でシェーダーをビルド
       └─ NodeBuilderStateを作成してキャッシュに保存
4. usedTimesをインクリメント
5. NodeBuilderStateを返却
```

#### updateGroup

```
1. グループ名を取得
2. objectGroupの場合：常にtrueを返却
3. renderGroupの場合：
   └─ 前回のrenderIdと比較
   └─ 異なればtrue、同じならfalse
4. frameGroupの場合：
   └─ 前回のframeIdと比較
   └─ 異なればtrue、同じならfalse
5. その他のグループ：
   └─ groupNode.versionを比較
   └─ 異なればtrue、同じならfalse
```

### フローチャート

```mermaid
flowchart TD
    A[getForRender開始] --> B{キャッシュにステートあり?}
    B -->|Yes| C[キャッシュから取得]
    B -->|No| D[キャッシュキーを計算]
    D --> E{キーでステートを検索}
    E -->|見つかった| F[既存ステートを使用]
    E -->|見つからない| G[NodeBuilderを作成]
    G --> H[環境ノード・フォグノードを設定]
    H --> I[build実行]
    I --> J[NodeBuilderStateを作成]
    J --> K[キャッシュに保存]
    F --> L[usedTimesをインクリメント]
    K --> L
    C --> L
    L --> M[NodeBuilderStateを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-175-01 | objectGroup常時更新 | objectGroupは毎フレーム更新 | updateGroup実行時 |
| BR-175-02 | renderGroup呼び出し単位 | renderGroupはrender/compute呼び出しごとに更新 | updateGroup実行時 |
| BR-175-03 | frameGroupフレーム単位 | frameGroupはフレームごとに更新 | updateGroup実行時 |
| BR-175-04 | ビルドエラー時フォールバック | TSLエラー時は空のNodeMaterialでリビルド | getForRender実行時 |
| BR-175-05 | キャッシュ参照カウント | usedTimesで参照を追跡し、0になったらキャッシュから削除 | delete実行時 |

### 計算ロジック

**キャッシュキーの計算**：
- レンダーオブジェクトのinitialCacheKeyを使用
- 環境ノード、フォグノード、ライトノードのキャッシュキーを結合
- シャドウマップ設定、マルチビュー設定を含む

**出力キャッシュキーの計算**：
```
outputCacheKey = toneMapping + ',' + currentColorSpace + ',' + xr.isPresenting
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TSLエラー | ビルドエラー | ノードグラフのビルド失敗 | エラーをログ出力し、空のNodeMaterialで再ビルド |
| 警告 | 設定警告 | サポートされない背景/フォグ設定 | コンソールに警告を出力 |

### リトライ仕様

ビルドエラー時は空のNodeMaterialを使用して再ビルドを試行

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

トランザクション処理は適用されない（メモリ上のキャッシュ管理）

## パフォーマンス要件

- キャッシュヒット時: O(1)でステートを取得
- キャッシュミス時: シェーダービルドのコストが発生（ビルド結果はキャッシュ）
- updateGroup: O(1)の比較処理

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

特になし（内部API）

## 備考

- NodeManagerはDataMapを継承しており、WeakMapベースのデータ管理を行う
- ChainMapは複数キーの組み合わせでキャッシュを管理するユーティリティ
- NodeFrameはフレームごとのノード更新状態を管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DataMap.js | `src/renderers/common/DataMap.js` | NodeManagerの基底クラス、WeakMapベースのデータ管理 |
| 1-2 | ChainMap.js | `src/renderers/common/ChainMap.js` | 複合キーによるキャッシュ管理 |
| 1-3 | NodeBuilderState.js | `src/renderers/common/nodes/NodeBuilderState.js` | ビルド結果の保持構造 |

**読解のコツ**: NodeManagerはDataMapを継承しており、get()/set()メソッドでオブジェクトに関連付けたデータを管理する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 33-87行目のコンストラクタとプロパティ定義 |

**主要処理フロー**:
1. **33-36行目**: コンストラクタでrendererとbackendを受け取る
2. **56行目**: nodeFrameはフレームごとの更新状態を管理
3. **63行目**: nodeBuilderCacheはキャッシュキーでステートを管理
4. **70行目**: callHashCacheはシーン・ライトノードのキャッシュキーを管理
5. **77行目**: groupsDataはユニフォームグループのデータを管理

#### Step 3: 主要メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 95-163行目 updateGroupメソッド |
| 3-2 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 183-249行目 getForRenderメソッド |
| 3-3 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 282-301行目 getForComputeメソッド |

**主要処理フロー**:
- **95-163行目**: updateGroup - グループ名に応じた更新判定
- **102行目**: objectGroupは常にtrue
- **106-121行目**: renderGroupはrenderIdで判定
- **125-140行目**: frameGroupはframeIdで判定
- **183-249行目**: getForRender - ノードビルダーステートの取得・生成
- **199-217行目**: NodeBuilderの作成と設定
- **222-233行目**: ビルドとエラーハンドリング

#### Step 4: シーンプロパティのノード変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 334-358行目 getEnvironmentNodeメソッド |
| 4-2 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 399-405行目 getFogNodeメソッド |
| 4-3 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 473-535行目 updateBackgroundメソッド |
| 4-4 | NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | 570-616行目 updateFogメソッド |

**主要処理フロー**:
- **473-535行目**: updateBackground - 背景テクスチャをノードに変換
- **486-508行目**: キューブマップ、環境マップの判定と変換
- **570-616行目**: updateFog - Fog/FogExp2をノードに変換
- **581-594行目**: FogExp2とFogの分岐処理

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

```
NodeManager
    │
    ├─ getForRender(renderObject)
    │      ├─ getForRenderCacheKey()
    │      ├─ backend.createNodeBuilder()
    │      ├─ getEnvironmentNode(scene)
    │      ├─ getFogNode(scene)
    │      ├─ nodeBuilder.build()
    │      └─ _createNodeBuilderState(nodeBuilder)
    │
    ├─ getForCompute(computeNode)
    │      ├─ backend.createNodeBuilder()
    │      ├─ nodeBuilder.build()
    │      └─ _createNodeBuilderState(nodeBuilder)
    │
    ├─ updateGroup(nodeUniformsGroup)
    │      └─ groupNode.name判定
    │
    ├─ getEnvironmentNode(scene)
    │      └─ updateEnvironment(scene)
    │
    ├─ getFogNode(scene)
    │      └─ updateFog(scene)
    │
    └─ getBackgroundNode(scene)
           └─ updateBackground(scene)
```

### データフロー図

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

RenderObject ────────────▶ getForRender() ──────────────────▶ NodeBuilderState
  │                              │                                │
  ├─ material                    ├─ キャッシュ検索                ├─ vertexShader
  ├─ camera                      │                                ├─ fragmentShader
  ├─ scene                       ├─ NodeBuilder作成               └─ bindings
  └─ lightsNode                  │
                                 ├─ getEnvironmentNode()
                                 │
                                 ├─ getFogNode()
                                 │
                                 └─ build()


Scene ───────────────────▶ updateBackground() ──────────────▶ backgroundNode
  │                              │
  ├─ background                  ├─ isCubeTexture判定
  └─ backgroundBlurriness        └─ pmremTexture/cubeTexture/texture

Scene.fog ───────────────▶ updateFog() ─────────────────────▶ fogNode
  │                              │
  ├─ isFogExp2                   ├─ densityFogFactor
  └─ isFog                       └─ rangeFogFactor
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NodeManager.js | `src/renderers/common/nodes/NodeManager.js` | ソース | ノードシステム管理の本体 |
| DataMap.js | `src/renderers/common/DataMap.js` | ソース | 基底クラス（WeakMapベース） |
| ChainMap.js | `src/renderers/common/ChainMap.js` | ソース | 複合キーキャッシュ |
| NodeBuilderState.js | `src/renderers/common/nodes/NodeBuilderState.js` | ソース | ビルド結果の保持 |
| NodeFrame.js | `src/nodes/core/NodeFrame.js` | ソース | フレーム更新管理 |
| NodeBuilder.js | `src/nodes/core/NodeBuilder.js` | ソース | シェーダービルダー |
| NodeMaterial.js | `src/materials/nodes/NodeMaterial.js` | ソース | フォールバックマテリアル |
