この章では、テクスチャ表示における様々なテクニックのうち、テクスチャが重なったときに加算合成を行う方法を紹介する。
複数のテクスチャが重なり合った時、通常は上にかぶさるように表示される。加算合成を行うと、重なった部分の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);
}
半透明処理で透明度を指定する際、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;
}
※上記修正を行い、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);
}
本来は背景画像の上にキャラクタを表示するため、このようなミスはしないと思われる。加算合成は、背景も含めて加算されることを覚えておこう。
| BACK(半透明表示) |