# 機能設計書 143-SphericalHarmonics3

## 概要

本ドキュメントは、Three.jsライブラリにおけるSphericalHarmonics3（球面調和関数）機能の設計について記述する。SphericalHarmonics3は、環境光を効率的に近似するための3次球面調和関数（SH3）を表現し、LightProbeでの環境照明に使用される。

### 本機能の処理概要

SphericalHarmonics3は、複雑な環境光情報を9つの係数（3次までの球面調和関数）で圧縮表現するクラスである。これにより、全方向からの環境光を低コストでシェーダー内で評価可能にする。

**業務上の目的・背景**：リアルタイム3Dグラフィックスでは、環境マップを直接サンプリングすることは計算コストが高い。球面調和関数を使用することで、環境光の低周波成分を9つの係数（各係数がRGB 3成分）に圧縮し、シェーダー内で効率的に評価できる。これはPBRにおけるディフューズ環境光の近似として広く使用されており、特にImage-Based Lighting（IBL）において重要な役割を果たす。学術的には、Stanford大学のRavi Ramamoorthi氏らの研究に基づいている。

**機能の利用シーン**：
- LightProbeを使用した環境照明
- 環境マップからの拡散照明の事前計算
- リアルタイムグローバルイルミネーション近似
- ベイクされた照明データの格納と再生
- 空間的に変化する環境光の補間

**主要な処理内容**：
1. 9つのSH係数（各Vector3）の管理
2. 任意の方向に対する放射輝度（Radiance）の計算
3. 任意の方向に対する放射照度（Irradiance）の計算
4. SH係数間の線形補間
5. SH係数のスケーリングと加算
6. SH基底関数の計算

**関連システム・外部連携**：
- LightProbeクラス（環境光源として使用）
- PMREMGenerator（環境マップからSH係数を生成）
- WebGLRenderer/WebGPURenderer（シェーダーでSH評価）

**権限による制御**：本機能は純粋な数学計算クラスであり、権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はUI画面に直接関連せず、内部の環境光計算として使用される |

## 機能種別

計算処理 / 球面調和関数

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| coefficients | Array<Vector3> | Yes | 9つのSH係数 | 長さ9の配列 |
| normal | Vector3 | Yes | 評価方向（単位ベクトル） | 正規化済みを想定 |
| sh | SphericalHarmonics3 | Yes | 演算対象のSH | SphericalHarmonics3インスタンス |
| s | number | Yes | スケール係数 | 任意の数値 |
| alpha | number | Yes | 補間係数 | 通常0-1の範囲 |
| array | Array<number> | Yes | フラット配列形式のSH係数 | 長さ27以上 |

### 入力データソース

- PMREMGeneratorからの環境マップ処理結果
- 外部ツールからのベイク済みSH係数
- シリアライズされたJSONデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| radiance | Vector3 | 指定方向の放射輝度 |
| irradiance | Vector3 | 指定方向の放射照度 |
| shBasis | Array<number> | SH基底関数の値（9要素） |
| coefficients | Array<Vector3> | SH係数配列 |

### 出力先

- シェーダーユニフォームへの転送
- JSON形式でのシリアライズ

## 処理フロー

### 処理シーケンス

```
1. SH係数の設定
   └─ set()またはfromArray()でcoefficientsを初期化
2. 方向ベクトルの正規化（呼び出し側の責任）
   └─ normalは単位ベクトルであることを前提
3. SH基底関数の計算
   └─ getBasisAt()で方向に対するSH基底を計算
4. 放射輝度/放射照度の評価
   └─ getAt()/getIrradianceAt()でドット積計算
5. 結果の返却
   └─ 計算結果をVector3で返却
```

### フローチャート

```mermaid
flowchart TD
    A[SH係数設定] --> B[方向ベクトル入力]
    B --> C{評価タイプ}
    C -->|放射輝度| D[getAt呼び出し]
    C -->|放射照度| E[getIrradianceAt呼び出し]
    D --> F[Band 0計算]
    E --> G[Band 0計算（コサインローブ重み付き）]
    F --> H[Band 1計算]
    G --> I[Band 1計算（コサインローブ重み付き）]
    H --> J[Band 2計算]
    I --> K[Band 2計算（コサインローブ重み付き）]
    J --> L[結果返却]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-143-01 | 係数数 | 常に9つの係数（Band 0-2） | 常時 |
| BR-143-02 | 単位ベクトル前提 | normalは正規化済みを想定 | getAt/getIrradianceAt |
| BR-143-03 | Band 0定数 | 0.282095（1/(2√π)） | SH基底計算 |
| BR-143-04 | Band 1定数 | 0.488603（√(3/(4π))） | SH基底計算 |

### 計算ロジック

**SH基底関数（getBasisAt）**：
```javascript
// Band 0
shBasis[0] = 0.282095

// Band 1
shBasis[1] = 0.488603 * y
shBasis[2] = 0.488603 * z
shBasis[3] = 0.488603 * x

// Band 2
shBasis[4] = 1.092548 * x * y
shBasis[5] = 1.092548 * y * z
shBasis[6] = 0.315392 * (3 * z * z - 1)
shBasis[7] = 1.092548 * x * z
shBasis[8] = 0.546274 * (x * x - y * y)
```

**放射輝度（getAt）**：係数とSH基底の重み付き和

**放射照度（getIrradianceAt）**：コサインローブで畳み込んだ係数を使用
- Band 0: π × 0.282095 ≈ 0.886227
- Band 1: (2π/3) × 0.488603 ≈ 2 × 0.511664
- Band 2: (π/4) × 係数

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

### 操作別データベース影響一覧

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | 本クラスは特別なエラー処理を行わない |

### リトライ仕様

該当なし（同期的な計算処理のため）

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

該当なし（データベース操作を行わないため）

## パフォーマンス要件

- getAt/getIrradianceAtは定数時間 O(1) で完了
- 9つの係数のみで環境光を近似するため、メモリ効率が高い
- シェーダー内評価も高速

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

特になし（純粋な数学計算クラス）

## 備考

- 3次SH（L=2）は環境光の低周波成分のみを表現
- 高周波成分（鏡面反射など）には別途環境マップが必要
- 参考文献：
  - https://graphics.stanford.edu/papers/envmap/envmap.pdf
  - https://www.ppsloan.org/publications/StupidSH36.pdf

---

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

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

### 推奨読解順序

#### Step 1: クラス構造と係数管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | コンストラクタとcoefficients配列（15-39行目） |
| 1-2 | SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | isSphericalHarmonics3フラグ（24行目） |

**読解のコツ**: coefficientsは9つのVector3で構成される。各Vector3はSH係数のRGB成分を表す。

#### Step 2: SH基底関数の計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | getBasisAt静的メソッド（316-337行目） |

**主要処理フロー**:
- **323行目**: Band 0 - 定数項（球面上で一様）
- **326-328行目**: Band 1 - y, z, x方向の線形項
- **331-335行目**: Band 2 - 2次の項（5つの基底）

#### Step 3: 放射輝度/放射照度の評価を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | getAtメソッド（84-109行目） |
| 3-2 | SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | getIrradianceAtメソッド（119-144行目） |

**主要処理フロー**:
- **93行目**: Band 0の寄与を初期化
- **96-98行目**: Band 1の寄与を加算
- **101-105行目**: Band 2の寄与を加算
- **128行目**: 放射照度用のBand 0係数（π重み付き）
- **136-140行目**: 放射照度用のBand 2係数（π/4重み付き）

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

```
SphericalHarmonics3
    │
    ├─ コンストラクタ
    │      └─ 9つのVector3を初期化
    │
    ├─ 係数操作メソッド
    │      ├─ set(coefficients)
    │      ├─ zero()
    │      ├─ add(sh)
    │      ├─ addScaledSH(sh, s)
    │      ├─ scale(s)
    │      └─ lerp(sh, alpha)
    │
    ├─ 評価メソッド
    │      ├─ getAt(normal, target)
    │      │      └─ 放射輝度計算
    │      └─ getIrradianceAt(normal, target)
    │             └─ 放射照度計算（コサインローブ畳み込み）
    │
    ├─ ユーティリティメソッド
    │      ├─ equals(sh)
    │      ├─ copy(sh)
    │      ├─ clone()
    │      ├─ fromArray(array, offset)
    │      └─ toArray(array, offset)
    │
    └─ 静的メソッド
           └─ getBasisAt(normal, shBasis)
                  └─ SH基底関数計算
```

### データフロー図

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

環境マップ ─────▶ PMREMGenerator ─────────▶ SH係数(9×RGB)
                  (事前処理)

                         ↓

normal + ───────▶ getAt() ─────────────────▶ radiance
SH係数            (SH基底×係数の和)          (Vector3)

normal + ───────▶ getIrradianceAt() ───────▶ irradiance
SH係数            (コサインローブ重み付き)    (Vector3)

normal ─────────▶ getBasisAt() ────────────▶ shBasis[]
                  (静的メソッド)             (9要素配列)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SphericalHarmonics3.js | `src/math/SphericalHarmonics3.js` | ソース | 球面調和関数クラス本体 |
| Vector3.js | `src/math/Vector3.js` | ソース | SH係数を格納するベクトルクラス |
| LightProbe.js | `src/lights/LightProbe.js` | ソース | SHを使用した環境光源 |
| PMREMGenerator.js | `src/extras/PMREMGenerator.js` | ソース | 環境マップからSH係数を生成 |
