【3Dゲーム開発#07】BlendStateを設定して半透明(アルファブレンド)処理

前回、頂点カラーを設定してポリゴンに色をつけられるようになりました。

その際、ColorはRGBAの値で設定しましたが、A(=Alpha)値については1.0(不透明)固定のままいじりませんでした。

というのも、Alpha値に関しては、単純にシェーダーでカラー出力すれば終わり、というものではなくブレンドの設定が必要となるためです。

ということで、今回はAlphaブレンド(半透明処理)ができるようにしていきます。

前回の記事:

【3Dゲーム開発#05】ポリゴンの座標変換② : 移動・回転・スケールの2D変換
前回までで、DirectXMathを使って行列の用意、シェーダーで座標変換、ができました。今回は、「移動」「回転」「スケール」それぞれの2D変換について詳しく見ていきましょう。また、座標変換は、単体で終わるものではなく、移動・回転・スケール...

3Dゲーム開発記事のまとめ:「3Dゲーム開発」

ブレンドステートを設定して半透明処理をする

BlendStateオブジェクトの作成

冒頭でも書きましたが、半透明処理にはブレンドの設定が必要となります。

具体的には

  • D3D11_BLEND_DESC型構造体にブレンドパラメータ設定
  • CreateBlendStateメソッドでBlendStateオブジェクト作成

そのために、ID3D11BlendState型のBlendStateオブジェクトを作成します。

    // RenderTarget0へのAlphaブレンド描画設定
    D3D11_BLEND_DESC BlendState;
    ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC));
    BlendState.AlphaToCoverageEnable = FALSE;
    BlendState.IndependentBlendEnable = FALSE;
    BlendState.RenderTarget[0].BlendEnable = TRUE;
    BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    hr = pD3DDevice_->CreateBlendState(&BlendState, &pBlendState_);
    if (FAILED(hr)) {
        //TRACE(L"InitDirect3D g_pD3DDevice->CreateBlendState", hr);
        return false;
    }

詳しいパラメータは以下の公式ドキュメントを参照ください。

D3D11_BLEND_DESC (d3d11.h) - Win32 apps
Describes the blend state that you use in a call to ID3D11Device::CreateBlendState to create a blend-state object.

この処理をRenderTargetの生成と合わせてやっておきましょう。

ですので、今までのプロジェクトのRenderer::initBackBuffer()で追記しておけばよいです。

BlendStateオブジェクトを設定

作成したBlendStateオブジェクトは、以下のメソッドで設定することで有効となります。

BlendFactorは、上記Blend設定で、RGBA個別にブレンド具体を指定したい場合の係数値です。かなり特殊なBlendをしようとしない限り使わないのであまり気にしなくてよいです。

第3引数は、どのRenderTargetをサンプルするかのMask(ビットフラグ)で、今はRenderTargetは1つなので基本的に考慮不要で0xffffffffを指定しておけばよいです(実際には1でよいです、0ではだめです)。

参考:公式:ID3D11DeviceContext::OMSetBlendState method

描画設定としてRenderer::Drawで呼び出しておきます。

void Renderer::Draw()
{
    ...

    // OMにブレンドステートオブジェクトを設定
    FLOAT BlendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
    pImmediateContext_->OMSetBlendState(pBlendState_, BlendFactor, 0xffffffff);

    ...
}

参考:出力マージャー(OutputMerger)とは

上記のインターフェースの通り、BlendStateはOM(出力マージャ)に設定しました。

出力マージャーとは、描画パイプラインでのほぼ最後のステージに相当して、ピクセルシェーダーで出力されたピクセルの色をRenderTargetへどう描き込むか決めるステージです。

ですので、Blend処理は、ピクセルシェーダーまではBlendStateとは無関係に色を計算し、この出力マージャー時点で、設定されたBlendStateに合わせて描き込まれる、ということです。

BlendState以外にも、Depth/Stencil(深度・ステンシル)テストの結果によって、そのピクセル描画をマスクするか、といったことも、出力マージャーステージで行う処理です。

BlendStateオブジェクトの破棄

生成したBlendStateオブジェクトは、他のDirectXリソースの破棄と同様にTerminateで破棄します。

void Renderer::Terminate()
{
    ...

    DX_SAFE_RELEASE(pBlendState_);

    ...
}

結果

ということで、TriangleでのAlpha値を適当に変えれば半透明(RenderTargetのクリア色の黒とアルファブレンド)になり、以下のように薄い色で描画されます。

vertex_color_alpha

ソースコード

以下が今回の実装があるコードです。

https://github.com/prog-log/GameDev/blob/master/04-VertexColor/RenderParam.cpp

コメント

タイトルとURLをコピーしました