# DirectXTK関連（Commonstateってなんぞ）

## ✅ 主な機能

<span style="white-space: pre-wrap;">CommonStates は以下のような「よくある組み合わせの状態オブジェクト」を提供します。 </span>[GitHub+1](https://github.com/microsoft/DirectXTK/wiki/CommonStates?utm_source=chatgpt.com)

- ブレンド状態（BlendState）
    - `<span class="editor-theme-code">Opaque()</span>`<span style="white-space: pre-wrap;"> : ブレンドなし（不透明）</span>
    - `<span class="editor-theme-code">AlphaBlend()</span>`<span style="white-space: pre-wrap;"> : アルファ付き（通常の透過）</span>
    - `<span class="editor-theme-code">Additive()</span>`<span style="white-space: pre-wrap;"> : 加算ブレンド（光・パーティクル用）</span>
    - `<span class="editor-theme-code">NonPremultiplied()</span>`<span style="white-space: pre-wrap;"> : プレマルチプライドでないアルファ用</span>
- 深度／ステンシル状態（DepthStencilState）
    - `<span class="editor-theme-code">DepthDefault()</span>`<span style="white-space: pre-wrap;"> : 通常の深度テスト＆書き込み</span>
    - `<span class="editor-theme-code">DepthNone()</span>`<span style="white-space: pre-wrap;"> : 深度テスト・書き込みとも無効</span>
    - `<span class="editor-theme-code">DepthRead()</span>`<span style="white-space: pre-wrap;"> : 深度確認はするが深度バッファ更新しない／透過用など</span>
    - `<span class="editor-theme-code">DepthReverseZ()</span>`／`<span class="editor-theme-code">DepthReadReverseZ()</span>`<span style="white-space: pre-wrap;"> : 反転Zバッファ使用時用</span>
- ラスタライザ状態（RasterizerState）
    - `<span class="editor-theme-code">CullNone()</span>`<span style="white-space: pre-wrap;"> : カリングなし（両面描画）</span>
    - `<span class="editor-theme-code">CullClockwise()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">CullCounterClockwise()</span>`<span style="white-space: pre-wrap;"> : カリング方向指定</span>
    - `<span class="editor-theme-code">Wireframe()</span>`<span style="white-space: pre-wrap;"> : ワイヤーフレームモード</span>
- サンプラ状態（SamplerState）
    - `<span class="editor-theme-code">PointWrap()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">PointClamp()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">LinearWrap()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">LinearClamp()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">AnisotropicWrap()</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">AnisotropicClamp()</span>`<span style="white-space: pre-wrap;"> : テクスチャサンプラの典型</span>

---

## 🧮 使い方（例）

```cpp
std::unique_ptr<DirectX::CommonStates> states = 
    std::make_unique<DirectX::CommonStates>(device);

deviceContext->OMSetBlendState(states->AlphaBlend(), nullptr, 0xFFFFFFFF);
deviceContext->OMSetDepthStencilState(states->DepthDefault(), 0);
deviceContext->RSSetState(states->CullCounterClockwise());
auto sampler = states->LinearWrap();
deviceContext->PSSetSamplers(0, 1, &sampler);
```

<span style="white-space: pre-wrap;">このように、状態オブジェクトを毎回自作せず「典型パターン」を </span>`<span class="editor-theme-code">states</span>`<span style="white-space: pre-wrap;"> から取得して使えます。 </span>[GitHub](https://github.com/microsoft/DirectXTK/wiki/CommonStates?utm_source=chatgpt.com)

---

## 🔍 なぜ使うといいか

- 状態オブジェクト（BlendState 等）の設定を毎回細かく書くと煩雑。CommonStates によって手軽に済む。
- 状態オブジェクトを重複して生成するのを防げる。状態生成は比較的コストがあるため。
- 読みやすく、間違えにくい。例えば「透過用に深度書き込みを止める」など典型パターンが明確。
- プロジェクトが大きくなっても「この状態セットを使えばOK」という共通の仕様にできる。

---

## ⚠️ 注意すべきこと

- CommonStates が提供する「典型の状態」がすべてのケースに最適とは限らない。カスタムなラスタ／ブレンド／深度設定が必要な場合は自分で構築する必要あり。
- 状態オブジェクトを頻繁に切り替えるとパフォーマンスに影響出る可能性あり。CommonStates とは別に描画順／バッチング／状態切り替えを整理するべき。
- サンプラ状態や深度モードを変更することで、既存の描画が崩れる可能性あり（例：カリングなし＋両面描画＝意図しない裏面が見える、深度無効＝描画順が重要になる）。
- ライブラリをリンク／設定ミスすると、「CommonStates の関数が未定義（Linker error）」になることが実際に質問として出ています

<p class="callout info">よく使う設定集</p>

`<span class="editor-theme-code">states</span>`<span style="white-space: pre-wrap;"> は </span>`<span class="editor-theme-code">std::make_unique<CommonStates>(device)</span>`<span style="white-space: pre-wrap;"> 済み前提です。</span>

---

# 1) 不透明3D（デフォルト）

- 用途：普通の3Dモデル（不透明）

```cpp
ctx->OMSetBlendState(states->Opaque(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthDefault(), 0);
ctx->RSSetState(states->CullCounterClockwise()); // 右手系ならCCW, 左手系なら適宜
```

- メモ：最初はこれ。描画順の考慮が少なくて済む。

---

# 2) 透明（アルファブレンド）

- 用途：ガラス/フェンス/半透明UI 等

```cpp
ctx->OMSetBlendState(states->AlphaBlend(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthRead(), 0); // 深度テストON/書き込みOFF
ctx->RSSetState(states->CullNone()); // 両面必要なら
```

- メモ：****後ろから前****の順に描く。深度書き込みOFFがコツ。

---

# 3) 加算（パーティクル/発光）

- 用途：火花・魔法・グローっぽいもの

```cpp
ctx->OMSetBlendState(states->Additive(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthRead(), 0);
ctx->RSSetState(states->CullNone());
```

- メモ：重なるほど明るくなる。順番は透明同様、奥→手前。

---

# 4) 2D/UI/スプライト

- 用途：テクスチャをそのまま貼るUI/スプライト

```cpp
ctx->OMSetBlendState(states->AlphaBlend(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthNone(), 0);
ctx->RSSetState(states->CullNone());
auto smp = states->LinearClamp(); // UIはClampが無難
ctx->PSSetSamplers(0, 1, &smp);
```

- メモ：****DepthNone****<span style="white-space: pre-wrap;"> にしておくのが楽。拡大縮小が多いなら Linear。</span>

---

# 5) スカイボックス

- 用途：立方体の内側に空を描く

```cpp
ctx->OMSetBlendState(states->Opaque(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthRead(), 0); // 背景なので書かない
ctx->RSSetState(states->CullNone()); // 内側を描くため
```

- メモ：ビュー行列の平行移動成分を消すのも忘れずに。

---

# 6) デバッグ（ワイヤーフレーム）

- 用途：ジオメトリ確認

```cpp
ctx->OMSetBlendState(states->Opaque(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthDefault(), 0);
ctx->RSSetState(states->Wireframe());
```

---

# 7) シャドウ用（深度のみパスの基本）

- 用途：単純な深度プリパスや影マップ（※深度バイアスは別途）

```cpp
ctx->OMSetBlendState(states->Opaque(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthDefault(), 0);
ctx->RSSetState(states->CullCounterClockwise());
// ピクセルシェーダを外す or 深度書き込み専用PSに
```

- メモ：CommonStates には深度バイアスは含まれないので、必要なら自作 RasterizerState を用意。

---

# 8) ポストプロセス（フルスクリーン）

- 用途：トーンマップ/ブラーなど

```cpp
ctx->OMSetBlendState(states->Opaque(), nullptr, 0xFFFFFFFF);
ctx->OMSetDepthStencilState(states->DepthNone(), 0);
ctx->RSSetState(states->CullNone());
auto smp = states->LinearClamp(); // スクリーンスペースはClampが基本
ctx->PSSetSamplers(0, 1, &smp);
```

---

# 9) サンプラの目安（用途別）

- ドット絵/ピクセルパーフェクト：`<span class="editor-theme-code">PointClamp()</span>`<span style="white-space: pre-wrap;"> / </span>`<span class="editor-theme-code">PointWrap()</span>`
- 一般/テクスチャ：`<span class="editor-theme-code">LinearWrap()</span>`<span style="white-space: pre-wrap;">（タイル） or </span>`<span class="editor-theme-code">LinearClamp()</span>`（UI/ポスト）
- 高品質リニア：`<span class="editor-theme-code">AnisotropicWrap()</span>`<span style="white-space: pre-wrap;"> / </span>`<span class="editor-theme-code">AnisotropicClamp()</span>`（斜めに見る床など）

---

# 10) Reverse-Z を使う場合（上級）

- 用途：遠距離のZ精度改善（プロジェクションと深度比較を反転）

```cpp
ctx->OMSetDepthStencilState(states->DepthReverseZ(), 0);        // 不透明
// or 透過時
ctx->OMSetDepthStencilState(states->DepthReadReverseZ(), 0);
```

- メモ：****射影行列のZも反転****が必要（アプリ側対応）。慣れてからでOK。

---

## 使い分けのコツ（超要約）

- ****不透明は DepthDefault / Opaque****、****透過は AlphaBlend / DepthRead****
- ****UI/ポストは DepthNone / CullNone****
- ****粒子は Additive or AlphaBlend****（内容で使い分け）
- ****スカイボックスは DepthRead / CullNone****
- <span style="white-space: pre-wrap;">サンプラは </span>****UI=Clamp、タイル=Wrap、品質=Anisotropic****