# 機能設計書 69-PointLight

## 概要

本ドキュメントは、Three.jsライブラリにおける点光源「PointLight」の機能設計について記述する。PointLightは、単一の点から全方向に光を放射する光源であり、電球のような光をシミュレートする。

### 本機能の処理概要

PointLightは、3D空間内の一点から全方向に均等に光を放射する光源クラスである。距離による減衰（アッテネーション）を持ち、シャドウマップによる影の生成が可能である。

**業務上の目的・背景**：現実世界の電球やランプは、一点から全方向に光を放射する。PointLightは、この点光源の特性をシミュレートするために使用される。距離減衰により、光源に近いほど明るく、遠いほど暗くなるリアルな照明効果を実現する。物理的に正確なレンダリング（PBR）では、逆二乗則による減衰（decay = 2）が使用される。

**機能の利用シーン**：
- 電球、ランプ、ろうそくなどの人工光源のシミュレーション
- 室内照明の表現
- 炎、火花などの光源効果
- 局所的な照明が必要なシーン
- ゲームのポイントライト照明

**主要な処理内容**：
1. 光源位置からの全方向放射
2. 距離による減衰計算
3. カンデラ（cd）単位の光度管理
4. シャドウマップによる全方向シャドウ生成

**関連システム・外部連携**：WebGLRenderer/WebGPURendererと連携。PointLightShadowによるキューブマップシャドウ生成。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 12 | Menubar - Add | 補助機能 | 点光源の追加 |
| 14 | Menubar - View | 補助機能 | ライトヘルパー表示切替 |

## 機能種別

データ定義 / 光源設定

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| color | number/Color/string | No | 光の色（デフォルト: 0xffffff） | Color.setで受け付ける形式 |
| intensity | number | No | 光の強度（カンデラ、デフォルト: 1） | 数値 |
| distance | number | No | 光の最大到達距離（0は無限、デフォルト: 0） | 数値 >= 0 |
| decay | number | No | 距離減衰係数（デフォルト: 2） | 数値 |

### 入力データソース

コンストラクタの引数から直接入力。positionで光源位置を制御。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isPointLight | boolean | 型判定用フラグ（常にtrue） |
| type | string | オブジェクトタイプ識別子（'PointLight'） |
| color | Color | 光の色（Lightから継承） |
| intensity | number | 光の強度（カンデラ、Lightから継承） |
| distance | number | 光の最大到達距離 |
| decay | number | 距離減衰係数 |
| shadow | PointLightShadow | シャドウ設定 |
| power | number | 光束（ルーメン、算出プロパティ） |

### 出力先

レンダラーに点光源情報として提供される。シャドウマップ（キューブマップ）が生成される。

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ super(color, intensity) - Lightのコンストラクタ実行
2. isPointLightフラグ設定
3. type設定
4. distance設定
5. decay設定
6. shadow = new PointLightShadow() でシャドウ設定初期化
7. シーンに追加
8. レンダリング時:
   a. 光源位置から全方向に光を放射
   b. 距離減衰を計算
   c. castShadow=trueの場合、キューブマップシャドウを生成
```

### フローチャート

```mermaid
flowchart TD
    A[new PointLight] --> B[super - Light初期化]
    B --> C[isPointLight = true]
    C --> D[type = 'PointLight']
    D --> E[distance設定]
    E --> F[decay設定]
    F --> G[shadow = new PointLightShadow]
    G --> H[初期化完了]
    H --> I[scene.add]
    I --> J{castShadow?}
    J -->|Yes| K[キューブマップシャドウ生成]
    J -->|No| L[影なし描画]
    K --> M[距離減衰計算]
    L --> M
    M --> N[全方向ライティング]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-1 | 全方向放射 | 光は位置から全方向に均等に放射される | 常時 |
| BR-69-2 | 距離減衰 | distance=0で無限距離、非0でカットオフあり | 常時 |
| BR-69-3 | 逆二乗則 | decay=2で物理的に正確な減衰 | PBRモード |
| BR-69-4 | power変換 | power = intensity * 4π（ルーメン⇔カンデラ変換） | power使用時 |
| BR-69-5 | キューブマップシャドウ | 全方向シャドウはキューブマップで生成 | 影生成時 |

### 計算ロジック

距離減衰計算:
```glsl
// distance = 0 の場合（無限距離）
attenuation = 1.0 / (lightDistance * lightDistance);

// distance > 0 の場合（カットオフあり）
attenuation = pow(saturate(-lightDistance / cutoffDistance + 1.0), decay);
```

power（光束）とintensity（光度）の変換:
```javascript
// カンデラからルーメン（等方性光源）
power = intensity * 4 * Math.PI;

// ルーメンからカンデラ
intensity = power / (4 * Math.PI);
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | パフォーマンス問題 | 多数のPointLightで影を有効にした場合 | ライト数を制限、影を無効化 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- シャドウマップ有効時は6方向のレンダリングが必要（キューブマップ）
- distance=0は計算コストが高い場合がある
- 複数のPointLightで影を有効にすると負荷が大幅に増加

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

特になし（クライアントサイドライブラリ）

## 備考

- 132行の実装
- シャドウマップはキューブマップ形式で全方向対応
- decay=2が物理的に正確（逆二乗則）
- 電球のW数からルーメンに変換してpowerに設定可能

---

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

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

### 推奨読解順序

#### Step 1: 親クラスを理解する

PointLightが継承するLightクラスの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Light.js | `src/lights/Light.js` | 親クラスの機能（color、intensity） |
| 1-2 | Object3D.js | `src/core/Object3D.js` | position、matrixの定義 |

**読解のコツ**: PointLightはpositionを光源位置として使用する点に注意。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PointLight.js | `src/lights/PointLight.js` | クラス全体（132行） |

**主要処理フロー**:
1. **1-2行目**: インポート（Light、PointLightShadow）
2. **19行目**: `class PointLight extends Light` - Light継承
3. **29行目**: コンストラクタ引数（color, intensity, distance, decay）
4. **31行目**: `super( color, intensity )` - Lightコンストラクタ呼び出し
5. **40行目**: `this.isPointLight = true` - 型判定フラグ
6. **42行目**: `this.type = 'PointLight'` - タイプ識別子
7. **54行目**: `this.distance = distance` - 距離設定
8. **63行目**: `this.decay = decay` - 減衰係数設定
9. **70行目**: `this.shadow = new PointLightShadow()` - シャドウ設定
10. **80-86行目**: power getter（intensity → lumens）
11. **88-93行目**: power setter（lumens → intensity）
12. **95-101行目**: dispose()メソッド
13. **103-114行目**: copy()メソッド
14. **116-127行目**: toJSON()メソッド

#### Step 3: シャドウ設定を確認する

PointLightShadowクラスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PointLightShadow.js | `src/lights/PointLightShadow.js` | PerspectiveCamera（FOV=90）でのシャドウ設定 |
| 3-2 | LightShadow.js | `src/lights/LightShadow.js` | シャドウ基底クラス |

**キーポイント**: PointLightShadowは90度FOVのPerspectiveCameraを使用（キューブマップの1面に対応）。

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

```
PointLight (継承: Light → Object3D → EventDispatcher)
    │
    ├─ constructor(color, intensity, distance, decay)
    │      │
    │      ├─ super(color, intensity) → Light.constructor()
    │      │
    │      ├─ this.isPointLight = true
    │      ├─ this.type = 'PointLight'
    │      ├─ this.distance = distance
    │      ├─ this.decay = decay
    │      └─ this.shadow = new PointLightShadow()
    │                              │
    │                              └─ new PerspectiveCamera(90, 1, 0.5, 500)
    │
    ├─ get power()
    │      └─ return this.intensity * 4 * Math.PI
    │
    ├─ set power(power)
    │      └─ this.intensity = power / (4 * Math.PI)
    │
    ├─ dispose()
    │      │
    │      ├─ super.dispose() → Light.dispose()
    │      └─ this.shadow.dispose()
    │
    ├─ copy(source)
    │      │
    │      ├─ super.copy(source)
    │      ├─ this.distance = source.distance
    │      ├─ this.decay = source.decay
    │      └─ this.shadow = source.shadow.clone()
    │
    └─ toJSON(meta)
           │
           ├─ super.toJSON(meta)
           ├─ data.object.distance = this.distance
           ├─ data.object.decay = this.decay
           └─ data.object.shadow = this.shadow.toJSON()
```

### データフロー図

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

color ─────────────▶ PointLight.constructor()
intensity                  │
distance                   ├─ Light初期化
decay                      ├─ distance設定
                           ├─ decay設定
                           └─ shadow = new PointLightShadow()
                                         │
                                         ▼
                              PointLightインスタンス
                                         │
                    ┌────────────────────┼────────────────────┐
                    ▼                    ▼                    ▼
              position              distance/decay          shadow
             (光源位置)             (減衰パラメータ)    PerspectiveCamera(90)
                    │                    │                    │
                    └────────────────────┼────────────────────┘
                                         │
                              距離減衰計算:
                              attenuation = 1/(d^decay)
                                         │
                                         ▼
                    ┌────────────────────┴────────────────────┐
                    ▼                                         ▼
           全方向ライティング                          キューブマップシャドウ生成
           (球状に光が放射)                     (6面×PerspectiveCamera)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PointLight.js | `src/lights/PointLight.js` | ソース | PointLightクラス定義（132行） |
| PointLightShadow.js | `src/lights/PointLightShadow.js` | ソース | シャドウ設定クラス（32行） |
| Light.js | `src/lights/Light.js` | ソース | 親クラス（Light） |
| LightShadow.js | `src/lights/LightShadow.js` | ソース | シャドウ基底クラス |
| Object3D.js | `src/core/Object3D.js` | ソース | 大親クラス |
| PerspectiveCamera.js | `src/cameras/PerspectiveCamera.js` | ソース | シャドウマップカメラ |
| PointLightHelper.js | `src/helpers/PointLightHelper.js` | ソース | 可視化ヘルパー |
