# 画面設計書 9-Simple Wasm Raytracer

## 概要

本ドキュメントは、.NET WebAssembly のレイトレーシングサンプル画面「Simple Wasm Raytracer」の設計内容を記載した画面設計書です。本画面は .NET Runtime リポジトリにおける WebAssembly のグラフィック処理能力をデモンストレーションするサンプルアプリケーションです。

### 本画面の処理概要

本画面は、ブラウザ上で .NET WebAssembly ランタイムを使用してレイトレーシング（光線追跡法）によるシンプルな 3D シーンのレンダリングを行い、640x480 ピクセルの Canvas に結果を表示するサンプルアプリケーションです。

**業務上の目的・背景**：本画面は、.NET WebAssembly ランタイムの数値計算性能とグラフィック処理能力を検証・デモンストレーションするために作成されました。レイトレーシングは計算集約型のアルゴリズムであり、WebAssembly の実行性能を測定するのに適しています。本サンプルでは、128 個のランダムな球体を含む 3D シーンをレンダリングし、ベクトル演算、ジェネリック型の動的インスタンス生成、SIMD 最適化の可能性などを示しています。

**画面へのアクセス方法**：ローカル開発サーバー（通常は `http://localhost:8000/`）にブラウザでアクセスすることで画面を表示できます。

**主要な操作・処理内容**：
1. 画面ロード時に JavaScript（main.js）が .NET WebAssembly ランタイムを初期化
2. C# の Main メソッドでシーン（128 個の球体）を初期化
3. 「Render」ボタンが有効化される
4. ユーザーが「Render」ボタンをクリック
5. C# の `OnClick()` メソッドでレイトレーシング計算を実行
6. 計算結果（RGBA バイト配列）を JavaScript に渡す
7. Canvas に ImageData として描画

**画面遷移**：本画面は単一画面のサンプルアプリケーションであり、他画面への遷移はありません。

**権限による表示制御**：本画面は認証・認可機能を持たないデモアプリケーションであり、権限による表示制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Mono | 主機能 | WebAssembly ランタイム上でレイトレーシング計算を実行 |
| 23 | System.Numerics.Tensors | 主機能 | ベクトル演算によるレイトレーシング計算 |
| 24 | System.Reflection.Emit | 補助機能 | ジェネリック型の動的インスタンス生成 |
| 59 | WebAssembly Workload | 補助機能 | WebAssembly アプリケーションのビルドと実行をサポート |

## 画面種別

インタラクティブデモ画面（単一画面）

## URL/ルーティング

- ローカル開発: `http://localhost:8000/index.html`
- 静的ファイルパス: `src/mono/sample/wasm/simple-raytracer/wwwroot/index.html`

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| - | - | - | 本画面にテキスト入力項目はありません |

## 表示項目

| 項目ID | 項目名 | 要素タイプ | 説明 |
|--------|--------|-----------|------|
| - | 画面タイトル | h1 | 「Simple wasm raytracer」と表示 |
| btnRender | Render ボタン | button | クリックでレンダリングを開始（初期状態: disabled） |
| out | Canvas | canvas | 640x480 ピクセルのレンダリング結果表示領域 |
| - | クレジット | p | 「Original implementation by Nicholas C. Bray」 |

## イベント仕様

### 1-画面ロード完了イベント

画面がロードされると、以下の処理が自動的に実行されます:

1. `main.js` がモジュールとして読み込まれる
2. `dotnet.create()` で WebAssembly ランタイムを初期化
3. `setModuleImports` で `renderCanvas` 関数を C# から呼び出せるように登録
4. `getAssemblyExports` で C# の公開メソッドを取得
5. `globalThis.onClick` に `exports.Program.OnClick` を設定
6. `dotnet.withRuntimeOptions(["--jiterpreter-stats-enabled"])` で Jiterpreter 統計を有効化
7. `runtime.runMain()` で C# の Main メソッドを実行（シーン初期化）
8. 「Render」ボタンを有効化（`disabled = false`）

### 2-Render ボタンクリック

1. `globalThis.onClick()` を呼び出し（HTML の onclick 属性から）
2. C# の `OnClick()` メソッドが実行される
3. `Raytrace.renderFrame()` でレイトレーシング計算を実行
4. 計算時間をコンソールに出力
5. `RenderCanvas(bytes)` で JavaScript に RGBA データを渡す
6. JavaScript の `renderCanvas()` で Canvas に描画

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面はデータベースを使用しません |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | 情報 | Hello, World! | C# Main メソッド実行時 |
| MSG-002 | 情報 | Rendering started | レンダリング開始時 |
| MSG-003 | 情報 | Rendering finished in {ms} ms | レンダリング完了時 |

## 例外処理

| 例外種別 | 発生条件 | 対応処理 |
|---------|---------|---------|
| 初期化エラー | ランタイム初期化失敗時 | コンソールにエラー出力 |

## 備考

- Canvas サイズ: 640x480 ピクセル
- シーン: 128 個のランダムな球体
- フレームバッファ: 640 * 480 * 4 バイト（RGBA）
- 乱数シード: 1（再現性のため固定）
- ベクトル演算: Vec3f 構造体を使用
- Intersector クラス: ジェネリック型でリフレクションを使用して動的生成
- `JSMarshalAs<JSType.MemoryView>` で ArraySegment を直接渡す
- `--jiterpreter-stats-enabled` で Jiterpreter 統計を有効化

---

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

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

### 推奨読解順序

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

まず、レイトレーシングで使用するデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Program.cs | `src/mono/sample/wasm/simple-raytracer/Program.cs` | Vec3f、Sphere 構造体、Intersector クラスを確認 |

**読解のコツ**: `Vec3f` は 3D ベクトル、`Sphere` は球体（中心、半径、色）を表します。`Intersector<T>` はレイと球体の交差判定を行うジェネリッククラスです。

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

処理の起点となるファイル・関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html | `src/mono/sample/wasm/simple-raytracer/wwwroot/index.html` | HTML 構造と Canvas 要素を確認 |
| 2-2 | main.js | `src/mono/sample/wasm/simple-raytracer/wwwroot/main.js` | ランタイム初期化と renderCanvas を確認 |

**主要処理フロー (main.js)**:
1. **6-14行目**: `renderCanvas` 関数 - Canvas に RGBA データを描画
2. **16-20行目**: `dotnet.create()` でランタイム初期化、setModuleImports
3. **21行目**: `globalThis.onClick` に C# メソッドを設定
4. **22-25行目**: Jiterpreter 統計有効化、runMain() 実行
5. **26-27行目**: Render ボタンを有効化

#### Step 3: C# 側のレイトレーシング実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Program.cs | `src/mono/sample/wasm/simple-raytracer/Program.cs` | Raytrace クラスと renderFrame メソッドを確認 |

**主要処理フロー (Program.cs)**:
- **9-19行目**: `Vec3f` 構造体 - 3D ベクトル
- **26-35行目**: `Sphere` 構造体 - 球体定義
- **37-281行目**: `Raytrace` クラス - レイトレーシングエンジン
- **243-258行目**: `renderFrame` - フレーム全体のレンダリング
- **260-280行目**: `init` - シーン初期化（128 個の球体生成）
- **283-302行目**: `Program` クラス - Main と OnClick

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

```
[Browser] index.html 読み込み
    |
    +-- [JavaScript] main.js 実行
            |
            +-- dotnet.create() - WebAssembly ランタイム初期化
            |
            +-- setModuleImports() - renderCanvas を公開
            |
            +-- getAssemblyExports() - C# メソッドを取得
            |
            +-- globalThis.onClick = exports.Program.OnClick
            |
            +-- runtime.runMain() - C# Main 実行
            |       |
            |       +-- [C#] Main()
            |               |
            |               +-- Raytrace.init()
            |                       |
            |                       +-- FrameBuffer = new byte[640*480*4]
            |                       +-- Scene = new Sphere[128]
            |                       +-- (ランダム球体生成)
            |
            +-- btnRender.disabled = false

[User] #btnRender クリック
    |
    +-- globalThis.onClick()
            |
            +-- [C#] OnClick()
                    |
                    +-- Console.WriteLine("Rendering started")
                    +-- Raytrace.renderFrame()
                    |       |
                    |       +-- for (j: 0..480)
                    |               +-- for (i: 0..640)
                    |                       +-- renderPixel(i, j, light, intersector)
                    |                               |
                    |                               +-- レイ生成
                    |                               +-- Intersector.Intersect() - 交差判定
                    |                               +-- シェーディング計算
                    |                               +-- FrameBuffer に書き込み
                    |
                    +-- Console.WriteLine("Rendering finished in {ms} ms")
                    +-- RenderCanvas(bytes)
                            |
                            +-- [JavaScript] renderCanvas(rgbaView)
                                    |
                                    +-- new Uint8ClampedArray(rgbaView)
                                    +-- new ImageData(clamped, 640, 480)
                                    +-- ctx.putImageData(image, 0, 0)
```

### データフロー図

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

Render ボタン --------> OnClick()
                            |
                            v
                     +-- renderFrame() ----+
                     |                     |
                     v                     |
              for each pixel (640x480)     |
                     |                     |
                     v                     |
              +-- renderPixel() ----+      |
              |                     |      |
              v                     v      |
        レイ生成            交差判定       |
              |                     |      |
              v                     v      |
        カメラ座標 -->      Intersector   |
        正規化方向          .Intersect()   |
                                    |      |
                                    v      |
                            交差あり？     |
                                    |      |
                      +-------------+      |
                      |             |      |
                      v             v      |
                  Yes           No        |
                      |             |      |
                      v             v      |
              シェーディング   環境光サンプル  |
              (拡散+鏡面)                   |
                      |             |      |
                      +------+------+      |
                             |             |
                             v             |
                      FrameBuffer に       |
                      RGBA 書き込み        |
                             |             |
                             +-------------+
                                    |
                                    v
                            FrameBuffer (byte[])
                                    |
                                    v
                            RenderCanvas()
                                    |
                                    v
                            [JavaScript]
                            ImageData --> Canvas
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html | `src/mono/sample/wasm/simple-raytracer/wwwroot/index.html` | テンプレート | HTML エントリーポイント、Canvas、Render ボタン |
| main.js | `src/mono/sample/wasm/simple-raytracer/wwwroot/main.js` | ソース | JavaScript エントリーポイント、Canvas 描画 |
| Program.cs | `src/mono/sample/wasm/simple-raytracer/Program.cs` | ソース | C# メインロジック、レイトレーシングエンジン |
| dotnet.js | `_framework/dotnet.js` | ランタイム | .NET WebAssembly ランタイムローダー（ビルド時生成） |
