加算合成

この章では、テクスチャ表示における様々なテクニックのうち、テクスチャが重なったときに加算合成を行う方法を紹介する。

加算合成とは?

複数のテクスチャが重なり合った時、通常は上にかぶさるように表示される。加算合成を行うと、重なった部分のRGBがそれぞれ加算され、結果、重なった部分が明るく表示されるようになる。
例えば、ポリゴン1の上にポリゴン2をかぶせる際に加算合成を行うと、次のように表示される(ポリゴン2の黒い部分は透明色とする)。

加算合成を指定すると、ポリゴン1とポリゴン2の画像が重なった部分が、明るくなっていることが分かる。これは、RGBそれぞれの要素で加算が行われており、RGBでは値が小さいほど暗くなり(0は黒)、値が大きいほど明るくなる(255は白)からである。
この技術を利用すれば、爆発やレーザーなどのテクスチャを使用する際、綺麗に見えるようになる。ただし、加算合成を意識したテクスチャを作らなければならないが・・・

加算合成の宣言

加算合成を行うには、描画設定処理を次のように修正しなければならない。

//-----------------------------------------------------------------------------
// 関数名 : InitRender()
// 機能概要: 描画の設定など
//-----------------------------------------------------------------------------
void InitRender(void)
{
    // テクスチャの設定
    gl_lpD3ddev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
    gl_lpD3ddev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    gl_lpD3ddev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);

    // アルファ・ブレンディングを行う
    gl_lpD3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    // 透過処理を行う
    gl_lpD3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    // 加算合成を行う
    gl_lpD3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
}

《POINT》

加算合成処理の使用

半透明処理で透明度を指定する際、0〜255の値を指定した。0が透明度100%で、255が透明度0%(透明にしない)であった。加算合成処理の場合、0が加算度100%で、255が加算度0%(加算合成をしない)である。
例えば、キャラクタ2を加算度100%で描画するには、ポリゴンの初期化処理を次のように設定すればよい。

//-----------------------------------------------------------------------------
// 関数名 : StartInit()
// 機能概要: スタート画面初期化処理
//-----------------------------------------------------------------------------
void StartInit(void)
{
    HRESULT ret;

    //--------------------------------------------------- 各変数の初期化
    // スタート画面で使用するテクスチャの作成
    CreateStartTexture();
    // 頂点データを格納する
    InitVertex(VertexDataTbl1, 100.0, 100.0, 300.0, 300.0, 255); // 加算合成を行わない
    InitVertex(VertexDataTbl2, 200.0, 200.0, 400.0, 400.0, 0); // 加算合成を行う

    //--------------------------------------------------- フレームナンバーセット
    g_FrameNo = START_FRAME;

}

《POINT》

※上記修正を行い、1つ目のキャラクタはそのままで、2つ目のキャラクタが加算合成が行われていることを確認する。

実行結果を見て分かるとおり、2つ目のキャラクタが、重なっている部分以外が消えてしまった。これは、加算合成は背景に対しても行われるため、白い背景に加算しても結果は白になってしまうからである。
よって、背景を黒色でクリアすれば、正しい結果を確認できる

//-----------------------------------------------------------------------------
// 関数名 : UpdateFrame()
// 機能概要: ゲームメイン処理
//-----------------------------------------------------------------------------
BOOL UpdateFrame(void)
{

    /* 現在のキー情報を取得 */
    if ( !GetKeyboardState(gl_KeyTbl) ) {
        MessageBox(hWnd, "キー情報の取得に失敗", "ERROR", MB_OK);
        return (FALSE);
    }

    /* 画面のクリア */
    gl_lpD3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 0.0, 0);
    /* シーン開始 */
    gl_lpD3ddev->BeginScene();
    /* 頂点フォーマットを設定 */
    gl_lpD3ddev->SetVertexShader(FVF_TLVERTEX);

    /* 処理の振り分け */
    switch ( g_FrameNo ) {
        case START_INIT:
            // スタート画面を表示する前に実行する初期化関数を実行
			StartInit();
        case START_FRAME:
            // スタート画面表示処理関数を実行
			StartFrame();
            break;
        case GAME_INIT:
            // ゲーム画面を表示する前に実行する初期化関数を実行
        case GAME_FRAME:
            // ゲーム画面表示処理関数を実行
            break;
        default:
            MessageBox(hWnd, "g_FrameNoの値が例外です。", "ERROR", MB_OK);
            return (FALSE);
    }

    /* シーン終了 */
    gl_lpD3ddev->EndScene();
    /* フリップ */
    gl_lpD3ddev->Present(NULL, NULL, NULL, NULL);

    return (TRUE);
}

《POINT》

本来は背景画像の上にキャラクタを表示するため、このようなミスはしないと思われる。加算合成は、背景も含めて加算されることを覚えておこう。


BACK(半透明表示)