# 機能設計書: 3Dレンダリング

## 1. 機能概要

### 1.1 機能の目的

3Dレンダリングシステムは、Godot Engineにおける3次元グラフィックスの描画基盤を提供する。VisualInstance3Dを基底クラスとして、メッシュ、ライト、カメラなどの3D要素をシーン内に配置し、RenderingServerと連携して効率的なGPUレンダリングを実現する。シャドウ、GI（グローバルイルミネーション）、LOD（Level of Detail）などの高度なレンダリング機能をサポートする。

### 1.2 主要な責務

| 責務 | 説明 |
|------|------|
| インスタンス管理 | RenderingServerとの3Dインスタンス連携 |
| 変換処理 | 3D空間でのローカル/グローバル変換 |
| 可視性制御 | レイヤーマスク、LOD、可視性範囲の管理 |
| メッシュ描画 | MeshInstance3Dによるメッシュ表示 |
| マテリアル管理 | オーバーライドマテリアル、サーフェスマテリアル |
| スケルトンアニメーション | ボーン変形とブレンドシェイプ |

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

```
+------------------+
|   Game Scripts   |
+------------------+
         |
         v
+------------------+     +------------------+
| MeshInstance3D   |---->|   Mesh Resource  |
+------------------+     +------------------+
         |                       |
         v                       v
+------------------+     +------------------+
|GeometryInstance3D|---->|   Material       |
+------------------+     +------------------+
         |
         v
+------------------+
| VisualInstance3D |  <-- 3D描画基盤クラス
+------------------+
         |
         v
+------------------+     +------------------+
|    Node3D        |<--->|    World3D       |
+------------------+     +------------------+
         |
         v
+------------------+
| RenderingServer  |  <-- GPU描画コマンド
+------------------+
```

## 2. クラス構造

### 2.1 クラス階層

```
Node
└── Node3D
    └── VisualInstance3D (scene/3d/visual_instance_3d.h)
        ├── base: RID                 // メッシュ等のベースリソース
        ├── instance: RID             // RenderingServerインスタンス
        ├── layers: uint32_t          // レンダーレイヤーマスク
        ├── sorting_offset: float     // ソートオフセット
        └── sorting_use_aabb_center: bool
            │
            └── GeometryInstance3D
                ├── shadow_casting_setting
                ├── material_override: Ref<Material>
                ├── material_overlay: Ref<Material>
                ├── visibility_range_*
                ├── transparency: float
                ├── lod_bias: float
                ├── gi_mode: GIMode
                └── extra_cull_margin: float
                    │
                    └── MeshInstance3D (scene/3d/mesh_instance_3d.h)
                        ├── mesh: Ref<Mesh>
                        ├── skin: Ref<Skin>
                        ├── skeleton_path: NodePath
                        ├── blend_shape_tracks: LocalVector<float>
                        └── surface_override_materials: Vector<Ref<Material>>
```

### 2.2 列挙型定義

```cpp
// scene/3d/visual_instance_3d.h 94-119行目
enum ShadowCastingSetting {
    SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF,
    SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON,
    SHADOW_CASTING_SETTING_DOUBLE_SIDED = RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED,
    SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY
};

enum GIMode {
    GI_MODE_DISABLED,  // GI無効
    GI_MODE_STATIC,    // 静的GI（ライトマップ）
    GI_MODE_DYNAMIC    // 動的GI
};

enum VisibilityRangeFadeMode {
    VISIBILITY_RANGE_FADE_DISABLED,   // フェード無効
    VISIBILITY_RANGE_FADE_SELF,       // 自身をフェード
    VISIBILITY_RANGE_FADE_DEPENDENCIES // 依存関係をフェード
};
```

## 3. 処理フロー

### 3.1 VisualInstance3D初期化フロー

```
[コンストラクタ]
        |
        v
+------------------+
| instance_create()|  <-- RenderingServerにインスタンス作成
+------------------+
        |
        v
+------------------+
| instance_attach_ |  <-- オブジェクトIDを関連付け
| object_instance_ |
| id()             |
+------------------+
        |
        v
+------------------+
| set_notify_      |  <-- 変換通知を有効化
| transform(true)  |
+------------------+
```

### 3.2 ワールド参入フロー

```
[NOTIFICATION_ENTER_WORLD]
        |
        v
+------------------+
| instance_set_    |  <-- シナリオに登録
| scenario()       |
+------------------+
        |
        v
+------------------+
| _update_         |  <-- 可視性更新
| visibility()     |
+------------------+
        |
        v
+------------------+
| instance_set_    |  <-- 変換を設定
| transform()      |
+------------------+
```

### 3.3 MeshInstance3Dメッシュ設定フロー

```
[set_mesh()呼び出し]
        |
        v
+------------------+
| 前のメッシュ切断 |
| (disconnect)     |
+------------------+
        |
        v
+------------------+
| mesh = p_mesh    |
+------------------+
        |
        v
+------------------+
| set_base()       |  <-- mesh->get_rid()をベースに設定
+------------------+
        |
        v
+------------------+
| connect_changed()|  <-- メッシュ変更監視
+------------------+
        |
        v
+------------------+
| _mesh_changed()  |  <-- ブレンドシェイプ/マテリアル更新
+------------------+
        |
        v
+------------------+
| notify_property_ |
| list_changed()   |
+------------------+
```

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

### 4.1 VisualInstance3D::_notification

```cpp
// scene/3d/visual_instance_3d.cpp 82-117行目
void VisualInstance3D::_notification(int p_what) {
    switch (p_what) {
        case NOTIFICATION_ENTER_WORLD: {
            ERR_FAIL_COND(get_world_3d().is_null());
            RenderingServer::get_singleton()->instance_set_scenario(instance, get_world_3d()->get_scenario());
            _update_visibility();
        } break;

        case NOTIFICATION_TRANSFORM_CHANGED: {
            if (_is_vi_visible() && !is_inside_tree() && get_tree()->is_physics_interpolation_enabled() && !_is_using_identity_transform()) {
                RenderingServer::get_singleton()->instance_set_transform(instance, get_global_transform());
            }
        } break;

        case NOTIFICATION_EXIT_WORLD: {
            RenderingServer::get_singleton()->instance_set_scenario(instance, RID());
            RenderingServer::get_singleton()->instance_attach_skeleton(instance, RID());
            _set_vi_visible(false);
        } break;

        case NOTIFICATION_VISIBILITY_CHANGED: {
            _update_visibility();
        } break;
    }
}
```

### 4.2 VisualInstance3D::_update_visibility

```cpp
// scene/3d/visual_instance_3d.cpp 41-59行目
void VisualInstance3D::_update_visibility() {
    if (!is_inside_tree()) {
        return;
    }

    bool already_visible = _is_vi_visible();
    bool visible = is_visible_in_tree();
    _set_vi_visible(visible);

    // 可視になった場合、変換を更新
    if (visible && !already_visible) {
        if (!_is_using_identity_transform()) {
            Transform3D gt = get_global_transform();
            RS::get_singleton()->instance_set_transform(instance, gt);
        }
    }

    RS::get_singleton()->instance_set_visible(instance, visible);
}
```

### 4.3 MeshInstance3D::set_mesh

```cpp
// scene/3d/mesh_instance_3d.cpp 112-137行目
void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
    if (mesh == p_mesh) {
        return;
    }

    if (mesh.is_valid()) {
        mesh->disconnect_changed(callable_mp(this, &MeshInstance3D::_mesh_changed));
    }

    mesh = p_mesh;

    if (mesh.is_valid()) {
        set_base(mesh->get_rid());
        mesh->connect_changed(callable_mp(this, &MeshInstance3D::_mesh_changed));
        _mesh_changed();
    } else {
        blend_shape_tracks.clear();
        blend_shape_properties.clear();
        set_base(RID());
        update_gizmos();
    }

    notify_property_list_changed();
}
```

### 4.4 MeshInstance3D::set_blend_shape_value

```cpp
// scene/3d/mesh_instance_3d.cpp 168-173行目
void MeshInstance3D::set_blend_shape_value(int p_blend_shape, float p_value) {
    ERR_FAIL_COND(mesh.is_null());
    ERR_FAIL_INDEX(p_blend_shape, (int)blend_shape_tracks.size());
    blend_shape_tracks[p_blend_shape] = p_value;
    RenderingServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), p_blend_shape, p_value);
}
```

### 4.5 GeometryInstance3D::set_material_override

```cpp
// scene/3d/visual_instance_3d.cpp 211-220行目
void GeometryInstance3D::set_material_override(const Ref<Material> &p_material) {
    if (material_override.is_valid()) {
        material_override->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
    }
    material_override = p_material;
    if (material_override.is_valid()) {
        material_override->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
    }
    RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
}
```

## 5. スケルトン連携

### 5.1 スケルトンパス解決

```cpp
// scene/3d/mesh_instance_3d.cpp 175-199行目
void MeshInstance3D::_resolve_skeleton_path() {
    Ref<SkinReference> new_skin_reference;

    if (!skeleton_path.is_empty()) {
        Skeleton3D *skeleton = Object::cast_to<Skeleton3D>(get_node_or_null(skeleton_path));
        if (skeleton) {
            if (skin_internal.is_null()) {
                new_skin_reference = skeleton->register_skin(skeleton->create_skin_from_rest_transforms());
                skin_internal = new_skin_reference->get_skin();
                notify_property_list_changed();
            } else {
                new_skin_reference = skeleton->register_skin(skin_internal);
            }
        }
    }

    skin_ref = new_skin_reference;

    if (skin_ref.is_valid()) {
        RenderingServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton());
    } else {
        RenderingServer::get_singleton()->instance_attach_skeleton(get_instance(), RID());
    }
}
```

## 6. コリジョン生成

### 6.1 Trimeshコリジョン生成

```cpp
// scene/3d/mesh_instance_3d.cpp 239-254行目
Node *MeshInstance3D::create_trimesh_collision_node() {
    if (mesh.is_null()) {
        return nullptr;
    }

    Ref<ConcavePolygonShape3D> shape = mesh->create_trimesh_shape();
    if (shape.is_null()) {
        return nullptr;
    }

    StaticBody3D *static_body = memnew(StaticBody3D);
    CollisionShape3D *cshape = memnew(CollisionShape3D);
    cshape->set_shape(shape);
    static_body->add_child(cshape, true);
    return static_body;
}
```

## 7. マテリアル優先順位

### 7.1 アクティブマテリアル取得

```cpp
// scene/3d/mesh_instance_3d.cpp 384-401行目
Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
    // 1. マテリアルオーバーライド（最優先）
    Ref<Material> mat_override = get_material_override();
    if (mat_override.is_valid()) {
        return mat_override;
    }

    Ref<Mesh> m = get_mesh();
    if (m.is_null() || m->get_surface_count() == 0) {
        return Ref<Material>();
    }

    // 2. サーフェスオーバーライドマテリアル
    Ref<Material> surface_material = get_surface_override_material(p_surface);
    if (surface_material.is_valid()) {
        return surface_material;
    }

    // 3. メッシュのサーフェスマテリアル
    return m->surface_get_material(p_surface);
}
```

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

### 8.1 推奨読解順序

1. **VisualInstance3Dの基本構造** (visual_instance_3d.h 37-86行目)
   - RID base, instanceの役割を理解
   - layersとsortingの仕組み

2. **初期化とライフサイクル** (visual_instance_3d.cpp 198-209行目)
   - コンストラクタでのinstance_create()
   - デストラクタでのfree_rid()

3. **ワールド連携** (visual_instance_3d.cpp 82-117行目)
   - NOTIFICATION_ENTER_WORLDでのシナリオ登録
   - 変換更新の仕組み

4. **GeometryInstance3D** (visual_instance_3d.h 88-214行目)
   - シャドウ、GI、LOD設定
   - マテリアルオーバーライド

5. **MeshInstance3D** (mesh_instance_3d.cpp 112-137行目)
   - メッシュ設定とRID連携
   - ブレンドシェイプ

### 8.2 読解のコツ

- `instance`はRenderingServerへの描画インスタンスハンドル
- `base`はメッシュなどのリソースRID
- `set_base()`で`instance`に`base`を関連付け
- `instance_set_transform()`で毎フレーム変換を送信
- `_mesh_changed()`でブレンドシェイプとマテリアルを同期

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

```
MeshInstance3D::set_mesh()
    |
    +---> VisualInstance3D::set_base()
    |         |
    |         +---> RS::instance_set_base()
    |
    +---> mesh->connect_changed(_mesh_changed)
    |
    +---> _mesh_changed()
              |
              +---> surface_override_materials.resize()
              |
              +---> blend_shape_tracks.resize()
              |
              +---> set_blend_shape_value()
              |         |
              |         +---> RS::instance_set_blend_shape_weight()
              |
              +---> RS::instance_set_surface_override_material()
              |
              +---> update_gizmos()
```

### 8.4 データフロー図

```
+----------------+     set_mesh()      +----------------+
|   GDScript     |-------------------->| MeshInstance3D |
+----------------+                      +----------------+
                                              |
                                              v
                                        set_base(RID)
                                              |
                                              v
+----------------+     instance RID     +----------------+
|RenderingServer |<--------------------| VisualInstance3D|
|                |                      |                |
|  instance_set_ |                      | instance: RID  |
|  base()        |                      | base: RID      |
|  transform()   |                      +----------------+
|  scenario()    |
+----------------+
        |
        v
+----------------+
|     GPU        |
+----------------+
```

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

| ファイル | 役割 |
|----------|------|
| `scene/3d/visual_instance_3d.h/cpp` | VisualInstance3D/GeometryInstance3D基底クラス |
| `scene/3d/mesh_instance_3d.h/cpp` | MeshInstance3D（メッシュ表示） |
| `scene/3d/node_3d.h/cpp` | Node3D（3D位置/回転/スケール） |
| `scene/3d/skeleton_3d.h/cpp` | スケルトンアニメーション |
| `scene/resources/mesh.h` | Meshリソース |
| `scene/resources/material.h` | Materialリソース |
| `servers/rendering/rendering_server.h` | レンダリングサーバーAPI |

## 9. 設計上の考慮点

### 9.1 パフォーマンス最適化

1. **LODシステム**: lod_biasで詳細度を距離に応じて調整
2. **可視性範囲**: visibility_range_*で遠距離オブジェクトを非表示
3. **レイヤーマスク**: 必要なオブジェクトのみレンダリング
4. **オクルージョンカリング**: ignore_occlusion_cullingで制御

### 9.2 マテリアル優先順位

```
1. material_override（GeometryInstance3D）
   ↓
2. surface_override_materials[i]（MeshInstance3D）
   ↓
3. mesh->surface_get_material(i)（Meshリソース）
```

### 9.3 シャドウ設定

| 設定 | 説明 |
|------|------|
| OFF | シャドウを投げない/受けない |
| ON | シャドウを投げる/受ける |
| DOUBLE_SIDED | 両面シャドウ |
| SHADOWS_ONLY | シャドウのみ（不可視） |

## 10. 通知定数

```cpp
// VisualInstance3Dで処理する通知
NOTIFICATION_ENTER_WORLD      // ワールド参入
NOTIFICATION_EXIT_WORLD       // ワールド退出
NOTIFICATION_TRANSFORM_CHANGED // 変換変更
NOTIFICATION_VISIBILITY_CHANGED // 可視性変更
NOTIFICATION_RESET_PHYSICS_INTERPOLATION // 物理補間リセット
```

## 11. 使用例

### 11.1 GDScriptでのMeshInstance3D使用

```gdscript
extends MeshInstance3D

func _ready():
    # メッシュ設定
    mesh = BoxMesh.new()
    mesh.size = Vector3(2, 2, 2)

    # マテリアル設定
    var material = StandardMaterial3D.new()
    material.albedo_color = Color.RED
    set_surface_override_material(0, material)

    # シャドウ設定
    cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_ON

    # GI設定
    gi_mode = GeometryInstance3D.GI_MODE_STATIC
```

### 11.2 ブレンドシェイプの使用

```gdscript
extends MeshInstance3D

func _process(delta):
    # ブレンドシェイプをアニメーション
    var value = sin(Time.get_ticks_msec() / 1000.0)
    set_blend_shape_value(0, value)
```

### 11.3 スケルトン連携

```gdscript
extends MeshInstance3D

func _ready():
    skeleton = get_node("../Skeleton3D")
    skeleton_path = skeleton.get_path()
```
