# GPUリソースを作っていく！→ Draw関数

## 🎮 GPUリソースを作るってどういうこと？

### 💡まずはイメージ！

- 「頂点の情報（場所や高さなど）」を作るだけでは、画面に出せません。
- <span style="white-space: pre-wrap;">作った情報を </span>****GPU****<span style="white-space: pre-wrap;"> に渡して、「これを描いて！」とお願いしないといけません。</span>

そのために、\*\*「バッファ」\*\*という入れ物を作って、GPUに渡す必要があります。

---

## 📦 GPUに送るデータは2つある！

<table id="bkmrk-%E5%90%8D%E5%89%8D%E8%AA%AC%E6%98%8E%E9%A0%82%E7%82%B9%E3%83%90%E3%83%83%E3%83%95%E3%82%A1%E7%82%B9%EF%BC%88%E5%A0%B4%E6%89%80%E3%83%BB%E9%AB%98%E3%81%95%E3%83%BB%E5%90%91%E3%81%8D"><colgroup><col></col><col></col></colgroup><tbody><tr><th>名前

</th><th>説明

</th></tr><tr><td>頂点バッファ

</td><td>点（場所・高さ・向き・UV）の情報

</td></tr><tr><td>インデックスバッファ

</td><td>どの点とどの点をつないで三角形にするか

</td></tr></tbody></table>

---

## 🧪 具体的にどうやるの？

### 🎯 頂点バッファを作る部分（簡略）

```cpp
D3D11_BUFFER_DESC vbDesc = {};
vbDesc.Usage = D3D11_USAGE_DEFAULT; // 普通の使い方
vbDesc.ByteWidth = sizeof(Vertex) * vertices_.size(); // 頂点のサイズぶん
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 頂点バッファだよ！

D3D11_SUBRESOURCE_DATA vbData = {};
vbData.pSysMem = vertices_.data(); // これが中身！

device->CreateBuffer(&vbDesc, &vbData, &vertexBuffer_);
```

---

### 🔺 インデックスバッファも同じ感じ

```cpp
D3D11_BUFFER_DESC ibDesc = {};
ibDesc.Usage = D3D11_USAGE_DEFAULT;
ibDesc.ByteWidth = sizeof(uint32_t) * indices_.size();
ibDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;

D3D11_SUBRESOURCE_DATA ibData = {};
ibData.pSysMem = indices_.data();

device->CreateBuffer(&ibDesc, &ibData, &indexBuffer_);
```

---

## 🔧 わかりやすく言うと…

1. `<span class="editor-theme-code">vbDesc</span>`<span style="white-space: pre-wrap;"> や </span>`<span class="editor-theme-code">ibDesc</span>`<span style="white-space: pre-wrap;"> に「バッファの情報（サイズとか）」を伝える</span>
2. `<span class="editor-theme-code">vbData</span>`<span style="white-space: pre-wrap;"> や </span>`<span class="editor-theme-code">ibData</span>`<span style="white-space: pre-wrap;"> に「実際の中身（点のデータなど）」を入れる</span>
3. `<span class="editor-theme-code">CreateBuffer()</span>`<span style="white-space: pre-wrap;"> で「バッファを作ってGPUに渡す」！</span>

---

## 🖼️ 絵にすると…

```text
[CPU]                      [GPU]
 vertices_ ───────▶ 頂点バッファ ┐
                               │→ 画面に表示！
 indices_  ───────▶ 三角形順バッファ┘
```

---

## 🧼 古いバッファはちゃんと片付けよう！

```cpp
if (vertexBuffer_) vertexBuffer_->Release();
if (indexBuffer_) indexBuffer_->Release();
```

これは「前のバッファがまだ残ってたら、片付けてから作ろうね！」というお片付けの処理です。

## 🧊Simple3Dシェーダを使ってレンダリングする

Simple3Dシェーダへの入力に合わせた、インプットレイアウトと（頂点の構造体）と、毎フレーム変更される情報を送るためのコンスタントバッファを作ります。  
  
🎨 1. 頂点の並び順（インプットレイアウト）

### 💡 そもそも「インプットレイアウト」ってなに？

GPUは「1つの頂点に何が入ってるのか」を知らないと、正しく使えません。  
そこで「この順番でデータが入ってるよ！」と教えるための設定が、****インプットレイアウト****です。

---

### 👇 このコードがその設定：

```cpp
D3D11_INPUT_ELEMENT_DESC layout[] = {
	{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },   // 座標（x, y, z）
	{ "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },  // 法線（x, y, z）
	{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },  // UV座標（u, v）
};
```

### 📦 つまり1頂点はこう：

<table id="bkmrk-%E3%83%90%E3%82%A4%E3%83%88%E4%BD%8D%E7%BD%AE%E5%86%85%E5%AE%B9%E3%82%B5%E3%82%A4%E3%82%BA0%E3%80%9C11positi"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr><th>バイト位置

</th><th>内容

</th><th>サイズ

</th></tr><tr><td>0〜11

</td><td>Position

</td><td>12バイト (

`<span class="editor-theme-code">float x,y,z</span>`

)

</td></tr><tr><td>12〜23

</td><td>Normal

</td><td>12バイト (

`<span class="editor-theme-code">float x,y,z</span>`

)

</td></tr><tr><td>24〜31

</td><td>UV

</td><td>8バイト (

`<span class="editor-theme-code">float u,v</span>`

)

</td></tr></tbody></table>

<span style="white-space: pre-wrap;">これを </span>`<span class="editor-theme-code">CreateInputLayout()</span>`<span style="white-space: pre-wrap;"> でGPUに登録して、「これに従って読み込んでね」と指示します。</span>

---

## 💡 2. 定数バッファ（CBGlobal）

### 🎒 頂点シェーダに渡す「カメラや光の情報」

描画時に使いたい「世界の情報（カメラ、ライティング、マトリクスなど）」は、毎フレーム変わるので、****定数バッファ****にまとめて送ります。

---

### <span style="white-space: pre-wrap;">✨ </span>`<span class="editor-theme-code">CBGlobal</span>`<span style="white-space: pre-wrap;"> 構造体の中身</span>

```cpp
struct CBGlobal {
    XMMATRIX g_matWVP;         // モデル→ビュー→プロジェクションの行列（最終位置）
    XMMATRIX g_matNormalTrans; // 法線用の変換行列
    XMMATRIX g_matWorld;       // モデルのワールド変換
    XMFLOAT4 g_vecLightDir;    // 光の向き
    XMFLOAT4 g_vecDiffuse;     // 拡散光の色
    XMFLOAT4 g_vecAmbient;     // 環境光の色
    XMFLOAT4 g_vecSpeculer;    // 鏡面反射の色
    XMFLOAT4 g_vecCameraPosition; // カメラの位置
    float g_shuniness;         // 鏡面反射の強さ
    BOOL g_isTexture;          // テクスチャありかなしか（フラグ）
    float pad[2];              // 16バイトにそろえるためのパディング
};
```

---

### 🔧 どう使われるの？

描画のときに、C++ 側で値をセットして GPU に送ります：

```cpp
Direct3D::pContext_->UpdateSubresource(globalCB, 0, nullptr, &cb, 0, 0);
Direct3D::pContext_->VSSetConstantBuffers(0, 1, &globalCB);
Direct3D::pContext_->PSSetConstantBuffers(0, 1, &globalCB);
```

このようにすると、HLSLのシェーダー側で次のように受け取れます：

```hlsl
cbuffer CBGlobal : register(b0)
{
    float4x4 g_matWVP;
    float4x4 g_matNormalTrans;
    float4x4 g_matWorld;
    float4 g_vecLightDir;
    ...
}
```

---

## 💫 最後にまとめると

<table id="bkmrk-%E3%83%91%E3%83%BC%E3%83%84%E5%90%8D%E5%BD%B9%E5%89%B2%E3%82%A4%E3%83%B3%E3%83%97%E3%83%83%E3%83%88%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E9%A0%82%E7%82%B9%E3%81%8C%E3%80%8C"><colgroup><col></col><col></col></colgroup><tbody><tr><th>パーツ名

</th><th>役割

</th></tr><tr><td>インプットレイアウト

</td><td>頂点が「どういう順番で並んでるか」をGPUに教える

</td></tr><tr><td>CBGlobal構造体

</td><td>カメラ・光・変換マトリクスなど、描画に必要な「毎回変わる情報」をまとめる

</td></tr></tbody></table>

## 🖼️ Draw関数を作って描画していく

地形（Terrain）が画面に出るようにする！  
基本は、今までやったQuadクラスとかの描画と一緒。

---

## 🪜 ステップで説明

---

### ✅ ① 頂点バッファとインデックスバッファをGPUに渡しておく（もうやった）

<span style="white-space: pre-wrap;">これは </span>`<span class="editor-theme-code">CreateBuffers()</span>`<span style="white-space: pre-wrap;"> の中でやりました。</span>  
「地形の形（点と三角形）」を GPU に教えてある状態です。

---

### ✅ ② シェーダーの準備（もうやった）

- 頂点シェーダ（VS）
- ピクセルシェーダ（PS）
- 入力レイアウト（頂点データの並び方）

<span style="white-space: pre-wrap;">これは </span>`<span class="editor-theme-code">InitShaderBundle()</span>`<span style="white-space: pre-wrap;"> で設定済みです。</span>

---

### 🆕 ③ 定数バッファにデータを入れて送る

`<span class="editor-theme-code">CBGlobal</span>`<span style="white-space: pre-wrap;"> に、プレイヤーの位置・カメラ・光の向きなどを詰めて送ります。</span>

```cpp
CBGlobal cb = {};
cb.g_matWVP = ...; // カメラを使った行列を計算して代入
cb.g_vecLightDir = { 0, -1, 1, 0 }; // 斜め上から光
...
context->UpdateSubresource(globalCB, 0, nullptr, &cb, 0, 0);
context->VSSetConstantBuffers(0, 1, &globalCB);
context->PSSetConstantBuffers(0, 1, &globalCB);
```

---

### 🆕 ④ GPU に地形データをセットする

地形の「点の情報」や「三角形のつなぎ方」を GPU に渡します。

```cpp
UINT stride = sizeof(Vertex); // 1つの頂点の大きさ
UINT offset = 0;
context->IASetVertexBuffers(0, 1, &vertexBuffer_, &stride, &offset);
context->IASetIndexBuffer(indexBuffer_, DXGI_FORMAT_R32_UINT, 0);
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 三角形で描くよ！
```

---

### 🆕 ⑤ テクスチャをGPUに渡す（画像つきの場合）

```cpp
ID3D11ShaderResourceView* srv = texture_->GetSRV();
context->PSSetShaderResources(0, 1, &srv);
```

---

### 🆕 ⑥ 実際に描く命令を出す！

ここで「GPUよ！描けー！」と命令します。

```cpp
context->DrawIndexed(static_cast<UINT>(indices_.size()), 0, 0);
```

これで、GPUが全部の三角形を使って地形を画面に出します。

---

## <span style="white-space: pre-wrap;">✅ 最終的な </span>`<span class="editor-theme-code">Draw()</span>`<span style="white-space: pre-wrap;"> の形</span>

```cpp
void Terrain::Draw(Transform& t)
{
    // ① 定数バッファを埋める
    CBGlobal cb = {};
    cb.g_matWVP = ...;
    ...
    context->UpdateSubresource(globalCB, 0, nullptr, &cb, 0, 0);
    context->VSSetConstantBuffers(0, 1, &globalCB);
    context->PSSetConstantBuffers(0, 1, &globalCB);

    // ② シェーダーを使う
    Direct3D::SetShader(Direct3D::SHADER_3D);

    // ③ 頂点とインデックスを渡す
    context->IASetVertexBuffers(...);
    context->IASetIndexBuffer(...);
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // ④ テクスチャを渡す
    context->PSSetShaderResources(0, 1, &texture_->GetSRV());

    // ⑤ 描画命令
    context->DrawIndexed(static_cast<UINT>(indices_.size()), 0, 0);
}
```

---

## 🎉 まとめ

<table id="bkmrk-%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%82%84%E3%82%8B%E3%81%93%E3%81%A8%E7%8A%B6%E6%85%8B%E2%91%A0-%E9%A0%82%E7%82%B9%E3%82%92%E4%BD%9C%E3%82%8Bmak"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr><th>ステップ

</th><th>やること

</th><th>状態

</th></tr><tr><td>① 頂点を作る

</td><td>`<span class="editor-theme-code">MakeTerrain()</span>`

などで作成済み

</td><td></td></tr><tr><td>② バッファ作る

</td><td>`<span class="editor-theme-code">CreateBuffers()</span>`

<span style="white-space: pre-wrap;"> 済み</span>

</td><td></td></tr><tr><td>③ シェーダーセット

</td><td>`<span class="editor-theme-code">InitShaderBundle()</span>`

<span style="white-space: pre-wrap;"> 済み</span>

</td><td></td></tr><tr><td>④ 定数バッファに情報入れる

</td><td>`<span class="editor-theme-code">Draw()</span>`

<span style="white-space: pre-wrap;"> 内でやる</span>

</td><td></td></tr><tr><td>⑤ 頂点・インデックス・テクスチャを渡す

</td><td>`<span class="editor-theme-code">Draw()</span>`

<span style="white-space: pre-wrap;"> 内でやる</span>

</td><td></td></tr><tr><td>⑥ 描画命令を出す

</td><td>`<span class="editor-theme-code">Draw()</span>`

<span style="white-space: pre-wrap;"> 内でやる</span>

</td></tr></tbody></table>

### おまけ

## 🎯 目的

地形の見た目を決める「シェーダー」の中身を作る！  
使うのは：

- 頂点シェーダ（VS）→ 三角形の位置を変える（カメラの向きなど）
- ピクセルシェーダ（PS）→ 色や明るさを決める（光やテクスチャ）

---

## 🧱 1. 共通で使う定数バッファ（C++と同じ構造）

```hlsl
cbuffer CBGlobal : register(b0)
{
    matrix g_matWVP;         // ワールド×ビュー×プロジェクション
    matrix g_matNormalTrans; // 法線の変換行列
    matrix g_matWorld;       // ワールド行列（モデル座標→ワールド）
    float4 g_vecLightDir;
    float4 g_vecDiffuse;
    float4 g_vecAmbient;
    float4 g_vecSpeculer;
    float4 g_vecCameraPosition;
    float g_shuniness;
    bool g_isTexture;
    float2 pad;
};
```

<span style="white-space: pre-wrap;">これは C++ 側の </span>`<span class="editor-theme-code">CBGlobal</span>`<span style="white-space: pre-wrap;"> とペアになります。カメラや光の情報をGPUに渡すための箱です。</span>

---

## 🧮 2. 頂点シェーダ VS

```hlsl
struct VS_IN
{
    float3 pos : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD;
};

struct VS_OUT
{
    float4 pos : SV_POSITION;
    float3 worldPos : POSITION1;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD;
};

VS_OUT VS(VS_IN input)
{
    VS_OUT output;

    float4 worldPos = mul(float4(input.pos, 1.0f), g_matWorld);
    output.pos = mul(worldPos, g_matWVP); // 画面に変換
    output.worldPos = worldPos.xyz;

    // 法線ベクトルの変換（回転だけ反映）
    output.normal = normalize(mul(float4(input.normal, 0.0f), g_matNormalTrans).xyz);

    output.uv = input.uv;
    return output;
}
```

### 🗺 何をやってる？

<table id="bkmrk-%E5%85%A5%E5%8A%9B%E3%82%84%E3%81%A3%E3%81%A6%E3%82%8B%E3%81%93%E3%81%A8%E5%87%BA%E5%8A%9B%E9%A0%82%E7%82%B9%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%82%AB%E3%83%A1%E3%83%A9%E8%A6%96%E7%82%B9"><colgroup><col></col><col></col><col></col></colgroup><tbody><tr><th>入力

</th><th>やってること

</th><th>出力

</th></tr><tr><td>頂点の位置

</td><td>カメラ視点の座標に変換

</td><td>`<span class="editor-theme-code">output.pos</span>`

（画面用）

</td></tr><tr><td>法線

</td><td>ライト計算できるように変換

</td><td>`<span class="editor-theme-code">output.normal</span>`

（ライト用）

</td></tr><tr><td>UV座標

</td><td>テクスチャの模様位置を受け渡す

</td><td>`<span class="editor-theme-code">output.uv</span>`

</td></tr></tbody></table>

---

## 🎨 3. ピクセルシェーダ PS

```hlsl
Texture2D tex0 : register(t0);
SamplerState smp : register(s0);

float4 PS(VS_OUT input) : SV_TARGET
{
    float3 normal = normalize(input.normal);
    float3 lightDir = normalize(-g_vecLightDir.xyz);

    // ランバート拡散
    float diff = max(dot(normal, lightDir), 0.0f);

    float3 ambient = g_vecAmbient.rgb;
    float3 diffuse = g_vecDiffuse.rgb * diff;

    // 鏡面反射（スペキュラ）
    float3 viewDir = normalize(g_vecCameraPosition.xyz - input.worldPos);
    float3 halfVec = normalize(lightDir + viewDir);
    float spec = pow(max(dot(normal, halfVec), 0.0f), g_shuniness);
    float3 specular = g_vecSpeculer.rgb * spec;

    float4 texColor = tex0.Sample(smp, input.uv);
    float3 finalColor = (ambient + diffuse + specular);

    if (g_isTexture)
        return float4(finalColor, 1.0f) * texColor;
    else
        return float4(finalColor, 1.0f);
}
```

### 💡 何をしてる？

<table id="bkmrk-%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E5%86%85%E5%AE%B9%E5%85%89%E3%81%AE%E5%90%91%E3%81%8D%E3%81%A8%E6%B3%95%E7%B7%9A%E3%81%AE%E8%A7%92%E5%BA%A6%E6%98%8E%E3%82%8B%E3%81%95%EF%BC%88"><colgroup><col></col><col></col></colgroup><tbody><tr><th>ステップ

</th><th>内容

</th></tr><tr><td>光の向きと法線の角度

</td><td>明るさ（影の強さ）を計算

</td></tr><tr><td>カメラと光の反射

</td><td>ピカっと光る所（ハイライト）を計算

</td></tr><tr><td>テクスチャと合成

</td><td>模様のある色と光の色を合成する

</td></tr></tbody></table>

---

## 🔚 まとめ

### シェーダーの流れ図

```txt
頂点データ（位置・法線・UV）
                        ↓
              [ 頂点シェーダ (VS) ]
                        ↓
         VS_OUT（画面座標・法線・UVなど）
                        ↓
             [ ピクセルシェーダ (PS) ]
                        ↓
         画面に出す最終の色（テクスチャ＋光）
```

---

## ✅ 最後に

このシェーダーは「リアルな明るさ＋テクスチャ模様」が出るようになっていて、  
以下のような構成をすべて活かしています：

- カメラ行列（WVP）
- ライト方向と色
- 法線の変換と補間
- テクスチャのUV座標