# 機能設計書: ライティング（2D/3D）

## 1. 機能概要

### 1.1 機能の目的

ライティングシステムは、Godot Engineにおける光源管理の基盤を提供する。3Dでは指向性光源（DirectionalLight3D）、点光源（OmniLight3D）、スポットライト（SpotLight3D）をサポートし、シャドウマッピング、ベイクモード、物理ベースの光源単位（ルーメン/ルクス）、色温度などの高度なライティング機能を実現する。

### 1.2 主要な責務

| 責務 | 説明 |
|------|------|
| 光源管理 | 各種光源タイプの作成と設定 |
| シャドウ制御 | シャドウマップの生成とパラメータ調整 |
| 減衰制御 | 距離に応じた光の減衰 |
| ベイクモード | 静的/動的ライトマップ対応 |
| 物理単位 | ルーメン/ルクス/色温度のサポート |
| 距離フェード | カメラ距離に応じたフェードアウト |

### 1.3 アーキテクチャ上の位置づけ

```
+------------------+
|   Game Scripts   |
+------------------+
         |
         v
+------------------+
|     Light3D      |  <-- 基底クラス
+------------------+
    /    |    \
   /     |     \
  v      v      v
+---------+ +----------+ +----------+
|Direction| |  Omni    | |  Spot    |
|alLight3D| | Light3D  | | Light3D  |
+---------+ +----------+ +----------+
         \      |      /
          \     |     /
           v    v    v
+------------------+
| VisualInstance3D |
+------------------+
         |
         v
+------------------+
| RenderingServer  |
+------------------+
```

## 2. クラス構造

### 2.1 クラス階層

```
VisualInstance3D
└── Light3D (scene/3d/light_3d.h)
    ├── light: RID                 // RenderingServer光源
    ├── type: RS::LightType        // 光源タイプ
    ├── color: Color               // 光源色
    ├── param[PARAM_MAX]: real_t   // パラメータ配列
    ├── shadow: bool               // シャドウ有効
    ├── bake_mode: BakeMode        // ベイクモード
    ├── temperature: float         // 色温度
    └── projector: Ref<Texture2D>  // プロジェクター
        │
        ├── DirectionalLight3D
        │   ├── shadow_mode: ShadowMode
        │   ├── sky_mode: SkyMode
        │   └── blend_splits: bool
        │
        ├── OmniLight3D
        │   └── shadow_mode: ShadowMode
        │
        └── SpotLight3D
```

### 2.2 Param列挙型

```cpp
// scene/3d/light_3d.h 39-62行目
enum Param {
    PARAM_ENERGY = RS::LIGHT_PARAM_ENERGY,           // エネルギー
    PARAM_INDIRECT_ENERGY,                           // 間接光エネルギー
    PARAM_VOLUMETRIC_FOG_ENERGY,                     // ボリュメトリックフォグ
    PARAM_SPECULAR,                                  // スペキュラー
    PARAM_RANGE,                                     // 範囲
    PARAM_SIZE,                                      // サイズ（ソフトシャドウ）
    PARAM_ATTENUATION,                               // 減衰
    PARAM_SPOT_ANGLE,                                // スポット角度
    PARAM_SPOT_ATTENUATION,                          // スポット減衰
    PARAM_SHADOW_MAX_DISTANCE,                       // シャドウ最大距離
    PARAM_SHADOW_SPLIT_1_OFFSET,                     // カスケード分割1
    PARAM_SHADOW_SPLIT_2_OFFSET,                     // カスケード分割2
    PARAM_SHADOW_SPLIT_3_OFFSET,                     // カスケード分割3
    PARAM_SHADOW_FADE_START,                         // シャドウフェード開始
    PARAM_SHADOW_NORMAL_BIAS,                        // 法線バイアス
    PARAM_SHADOW_BIAS,                               // シャドウバイアス
    PARAM_SHADOW_PANCAKE_SIZE,                       // パンケーキサイズ
    PARAM_SHADOW_OPACITY,                            // シャドウ不透明度
    PARAM_SHADOW_BLUR,                               // シャドウブラー
    PARAM_TRANSMITTANCE_BIAS,                        // 透過バイアス
    PARAM_INTENSITY,                                 // 強度（ルーメン/ルクス）
    PARAM_MAX
};
```

### 2.3 BakeMode列挙型

```cpp
// scene/3d/light_3d.h 64-68行目
enum BakeMode {
    BAKE_DISABLED,   // ベイク無効
    BAKE_STATIC,     // 静的ベイク
    BAKE_DYNAMIC,    // 動的ベイク
};
```

## 3. 処理フロー

### 3.1 光源初期化フロー

```
[Light3D(LightType)]
        |
        v
+------------------+
| type別にlight作成|
| - directional    |
| - omni           |
| - spot           |
+------------------+
        |
        v
+------------------+
| instance_set_base|  <-- light RIDをベースに設定
| (light)          |
+------------------+
        |
        v
+------------------+
| デフォルトパラメ |
| ータ設定         |
+------------------+
        |
        v
[初期化完了]
```

### 3.2 パラメータ設定フロー

```
[set_param(p_param, p_value)]
        |
        v
+------------------+
| param[p_param]   |
| = p_value        |
+------------------+
        |
        v
+------------------+
| RS::light_set_   |
| param()          |
+------------------+
        |
        v
+------------------+
| SPOT_ANGLE/RANGE |  --> update_gizmos()
| の場合           |
+------------------+
```

### 3.3 色温度変換フロー

```
[set_temperature(p_temperature)]
        |
        v
+------------------+
| temperature =    |
| p_temperature    |
+------------------+
        |
        v
+------------------+
| _color_from_     |  <-- CIE 1960からsRGBへ変換
| temperature()    |
+------------------+
        |
        v
+------------------+
| combined =       |
| color * corr     |
+------------------+
        |
        v
+------------------+
| RS::light_set_   |
| color(combined)  |
+------------------+
```

## 4. 主要メソッド詳細

### 4.1 Light3Dコンストラクタ

```cpp
// scene/3d/light_3d.cpp 450-498行目
Light3D::Light3D(RenderingServer::LightType p_type) {
    type = p_type;
    switch (p_type) {
        case RS::LIGHT_DIRECTIONAL:
            light = RenderingServer::get_singleton()->directional_light_create();
            break;
        case RS::LIGHT_OMNI:
            light = RenderingServer::get_singleton()->omni_light_create();
            break;
        case RS::LIGHT_SPOT:
            light = RenderingServer::get_singleton()->spot_light_create();
            break;
    }

    RS::get_singleton()->instance_set_base(get_instance(), light);

    set_color(Color(1, 1, 1, 1));
    set_shadow(false);
    set_param(PARAM_ENERGY, 1);
    set_param(PARAM_INDIRECT_ENERGY, 1);
    set_param(PARAM_RANGE, 5);
    set_param(PARAM_SPOT_ANGLE, 45);
    set_param(PARAM_INTENSITY, 1000.0);
    set_temperature(6500.0);
    // ...
}
```

### 4.2 set_param（パラメータ設定）

```cpp
// scene/3d/light_3d.cpp 35-48行目
void Light3D::set_param(Param p_param, real_t p_value) {
    ERR_FAIL_INDEX(p_param, PARAM_MAX);
    param[p_param] = p_value;

    RS::get_singleton()->light_set_param(light, RS::LightParam(p_param), p_value);

    if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) {
        update_gizmos();

        if (p_param == PARAM_SPOT_ANGLE) {
            update_configuration_warnings();
        }
    }
}
```

### 4.3 set_shadow（シャドウ設定）

```cpp
// scene/3d/light_3d.cpp 55-60行目
void Light3D::set_shadow(bool p_enable) {
    shadow = p_enable;
    RS::get_singleton()->light_set_shadow(light, p_enable);

    update_configuration_warnings();
}
```

### 4.4 set_color（色設定）

```cpp
// scene/3d/light_3d.cpp 121-133行目
void Light3D::set_color(const Color &p_color) {
    color = p_color;

    if (GLOBAL_GET_CACHED(bool, "rendering/lights_and_shadows/use_physical_light_units")) {
        // 物理ベースの光源単位使用時
        Color combined = color.srgb_to_linear();
        combined *= correlated_color.srgb_to_linear();
        RS::get_singleton()->light_set_color(light, combined.linear_to_srgb());
    } else {
        RS::get_singleton()->light_set_color(light, color);
    }

    update_gizmos();
}
```

### 4.5 _color_from_temperature（色温度変換）

```cpp
// scene/3d/light_3d.cpp 232-255行目
Color _color_from_temperature(float p_temperature) {
    // ケルビン温度からCIE 1960色空間に変換
    float T2 = p_temperature * p_temperature;
    float u = (0.860117757f + 1.54118254e-4f * p_temperature + 1.28641212e-7f * T2) /
            (1.0f + 8.42420235e-4f * p_temperature + 7.08145163e-7f * T2);
    float v = (0.317398726f + 4.22806245e-5f * p_temperature + 4.20481691e-8f * T2) /
            (1.0f - 2.89741816e-5f * p_temperature + 1.61456053e-7f * T2);

    // xyY空間に変換
    float d = 1.0f / (2.0f * u - 8.0f * v + 4.0f);
    float x = 3.0f * u * d;
    float y = 2.0f * v * d;

    // XYZ空間に変換
    const float a = 1.0 / MAX(y, 1e-5f);
    Vector3 xyz = Vector3(x * a, 1.0, (1.0f - x - y) * a);

    // XYZからsRGB(linear)に変換
    Vector3 linear = Vector3(
        3.2404542f * xyz.x - 1.5371385f * xyz.y - 0.4985314f * xyz.z,
        -0.9692660f * xyz.x + 1.8760108f * xyz.y + 0.0415560f * xyz.z,
        0.0556434f * xyz.x - 0.2040259f * xyz.y + 1.0572252f * xyz.z);

    return Color(linear.x, linear.y, linear.z).clamp().linear_to_srgb();
}
```

### 4.6 get_aabb（境界ボックス取得）

```cpp
// scene/3d/light_3d.cpp 157-178行目
AABB Light3D::get_aabb() const {
    if (type == RenderingServer::LIGHT_DIRECTIONAL) {
        return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
    } else if (type == RenderingServer::LIGHT_OMNI) {
        return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]);
    } else if (type == RenderingServer::LIGHT_SPOT) {
        real_t cone_slant_height = param[PARAM_RANGE];
        real_t cone_angle_rad = Math::deg_to_rad(param[PARAM_SPOT_ANGLE]);

        if (cone_angle_rad > Math::PI / 2.0) {
            return AABB(Vector3(-1, -1, -1) * cone_slant_height, Vector3(2, 2, 2) * cone_slant_height);
        }

        real_t size = Math::sin(cone_angle_rad) * cone_slant_height;
        return AABB(Vector3(-size, -size, -cone_slant_height), Vector3(2 * size, 2 * size, cone_slant_height));
    }

    return AABB();
}
```

## 5. 派生クラス

### 5.1 DirectionalLight3D

```cpp
// scene/3d/light_3d.h 162-198行目
class DirectionalLight3D : public Light3D {
    GDCLASS(DirectionalLight3D, Light3D);

    enum ShadowMode {
        SHADOW_ORTHOGONAL,         // 正射影シャドウ
        SHADOW_PARALLEL_2_SPLITS,  // 2分割カスケード
        SHADOW_PARALLEL_4_SPLITS,  // 4分割カスケード
    };

    enum SkyMode {
        SKY_MODE_LIGHT_AND_SKY,    // 光源とスカイ両方
        SKY_MODE_LIGHT_ONLY,       // 光源のみ
        SKY_MODE_SKY_ONLY,         // スカイのみ
    };

    bool blend_splits;      // 分割ブレンド
    ShadowMode shadow_mode; // シャドウモード
    SkyMode sky_mode;       // スカイモード
};
```

### 5.2 OmniLight3D

```cpp
// scene/3d/light_3d.h 203-226行目
class OmniLight3D : public Light3D {
    GDCLASS(OmniLight3D, Light3D);

    enum ShadowMode {
        SHADOW_DUAL_PARABOLOID,  // 双放物線マップ
        SHADOW_CUBE,             // キューブマップ
    };

    ShadowMode shadow_mode;
};
```

### 5.3 SpotLight3D

```cpp
// scene/3d/light_3d.h 230-240行目
class SpotLight3D : public Light3D {
    GDCLASS(SpotLight3D, Light3D);
    // SpotLight3D固有のメンバはなし
    // PARAM_SPOT_ANGLE, PARAM_SPOT_ATTENUATIONで制御
};
```

## 6. 距離フェード

```cpp
// scene/3d/light_3d.cpp 75-110行目
void Light3D::set_enable_distance_fade(bool p_enable) {
    distance_fade_enabled = p_enable;
    RS::get_singleton()->light_set_distance_fade(light,
        distance_fade_enabled,
        distance_fade_begin,
        distance_fade_shadow,
        distance_fade_length);
    notify_property_list_changed();
}
```

| プロパティ | 説明 |
|------------|------|
| distance_fade_enabled | フェード有効/無効 |
| distance_fade_begin | フェード開始距離 |
| distance_fade_shadow | シャドウフェード距離 |
| distance_fade_length | フェード完了までの距離 |

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

### 7.1 推奨読解順序

1. **Light3Dクラス構造** (light_3d.h 35-157行目)
   - Param列挙型とメンバ変数

2. **コンストラクタ** (light_3d.cpp 450-498行目)
   - 光源タイプ別の初期化

3. **set_param()** (light_3d.cpp 35-48行目)
   - RenderingServerへのパラメータ設定

4. **色温度変換** (light_3d.cpp 232-255行目)
   - CIE 1960からsRGBへの変換

5. **派生クラス** (light_3d.h 162-240行目)
   - DirectionalLight3D/OmniLight3D/SpotLight3D

### 7.2 読解のコツ

- `param[PARAM_MAX]`配列はRenderingServerのパラメータと対応
- `light` RIDはVisualInstance3Dの`base`として設定される
- 物理単位使用時は`srgb_to_linear()` / `linear_to_srgb()`変換が必要
- `correlated_color`は色温度から計算された色

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

```
Light3D::set_param()
    |
    +---> param[p_param] = p_value
    |
    +---> RS::light_set_param()
    |
    +---> update_gizmos() [SPOT_ANGLE/RANGEの場合]

Light3D::set_color()
    |
    +---> color = p_color
    |
    +---> [物理単位使用時]
    |         |
    |         +---> srgb_to_linear()
    |         |
    |         +---> * correlated_color
    |         |
    |         +---> linear_to_srgb()
    |
    +---> RS::light_set_color()
    |
    +---> update_gizmos()
```

### 7.4 データフロー図

```
+----------------+     set_param()      +----------------+
|   GDScript     |--------------------->|   Light3D      |
+----------------+                       +----------------+
                                               |
                                               v
                                        param[p_param]
                                               |
                                               v
+----------------+     light_set_param() +----------------+
|RenderingServer |<----------------------|    RID light   |
|                |                       +----------------+
| light_set_     |
| color/shadow/  |
| distance_fade  |
+----------------+
        |
        v
+----------------+
|   GPU Shader   |
+----------------+
```

### 7.5 関連ファイル一覧

| ファイル | 役割 |
|----------|------|
| `scene/3d/light_3d.h/cpp` | Light3Dと派生クラス |
| `scene/3d/visual_instance_3d.h/cpp` | 基底クラス |
| `servers/rendering/rendering_server.h` | ライティングAPI |
| `scene/resources/environment.h` | 環境設定 |

## 8. 物理ベース光源単位

### 8.1 ルーメン/ルクス

| 光源タイプ | 単位 | 説明 |
|------------|------|------|
| DirectionalLight3D | ルクス (lx) | 照度（単位面積あたりの光束） |
| OmniLight3D | ルーメン (lm) | 光束（光源の全放射エネルギー） |
| SpotLight3D | ルーメン (lm) | 光束 |

### 8.2 色温度

| 温度 (K) | 色調 |
|----------|------|
| 1000 | 暖色（ろうそく） |
| 3000 | 電球色 |
| 5500 | 昼光色 |
| 6500 | 白色（デフォルト） |
| 10000 | 青白色 |

## 9. 使用例

### 9.1 基本的なライト設定

```gdscript
extends OmniLight3D

func _ready():
    # 色と強度
    light_color = Color.WHITE
    light_energy = 1.0

    # 範囲と減衰
    omni_range = 10.0
    omni_attenuation = 1.0

    # シャドウ
    shadow_enabled = true
    shadow_bias = 0.1
```

### 9.2 物理ベースライティング

```gdscript
extends SpotLight3D

func _ready():
    # 物理単位（Project Settings で有効化必要）
    light_intensity_lumens = 1000.0
    light_temperature = 5500.0  # 昼光色

    # スポットライト設定
    spot_range = 20.0
    spot_angle = 45.0
```

### 9.3 距離フェード

```gdscript
extends OmniLight3D

func _ready():
    distance_fade_enabled = true
    distance_fade_begin = 50.0
    distance_fade_shadow = 40.0
    distance_fade_length = 10.0
```
