3

私は DirectX 9 を使用してゲームに取り組んでいます。これが私がやろうとしていることです:

シーンがレンダリングされた後、その上にいくつかのスプライトをレンダリングしたいと思います。シーン全体の黒いカバーと、カバーに穴が必要な場所を示すマスクであるいくつかのスプライトです。これまでのところ、ブレンドモードをいじってみましたが、うまくいきませんでした。それを設定する私のコードは次のようになります。

D3DD->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
D3DD->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3DD->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

各スプライトのアルファを乗算するのが最善の方法だと思いますが、http://msdn.microsoft.com/en-us/library/windows/desktop/bb172508%28v=vs.85%29.aspxによると、そのようなモードはありませんがサポートされています。これを行う別の方法はありますか?

edit

Nico Schertler's answer に従って、私が思いついたコードは次のとおりです。

LPDIRECT3DTEXTURE9      pRenderTexture;
LPDIRECT3DSURFACE9      pRenderSurface,
                        pBackBuffer;

// create texture
D3DD->CreateTexture(1024,
                    1024,
                    1,
                    D3DUSAGE_RENDERTARGET,
                    D3DFMT_R5G6B5,
                    D3DPOOL_DEFAULT,
                    &pRenderTexture,
                    NULL);

pRenderTexture->GetSurfaceLevel(0,&pRenderSurface);

// store old render target - back buffer
D3DD->GetRenderTarget(0,&pBackBuffer);

// set new render target - texture
D3DD->SetRenderTarget(0,pRenderSurface);

//clear texture to opaque black
D3DD->Clear(0,
            NULL,
            D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
            D3DCOLOR_XRGB(0,0,0),
            32.0f,
            0);

// set blending
D3DD->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
D3DD->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
D3DD->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ZERO);
D3DD->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_SRCALPHA);
D3DD->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);

//// now I render hole sprites the usual way

// restore back buffe as render target
D3DD->SetRenderTarget(0,pBackBuffer);

// restore blending
D3DD->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3DD->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
D3DD->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_SRCALPHA);
D3DD->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
D3DD->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);

ulong color = ulong(-1);
Vertex2D v[4];

v[0] = Vertex2D(0, 0, 0);
v[1] = Vertex2D(1023, 0, 0);
v[3] = Vertex2D(1023, 1023, 0);
v[2] = Vertex2D(0, 1023, 0);

D3DD->SetTexture(0, pRenderTexture);
D3DD->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
D3DD->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, v, sizeof(Vertex2D));

D3DD->SetTexture(0, NULL);

// release used resources
pRenderTexture->Release();
pRenderSurface->Release();
pBackBuffer->Release();

残念ながら、古いレンダー ターゲットを復元するとアプリがクラッシュします。何かアドバイス?

4

1 に答える 1

1

まず、最初に別のテクスチャでマスクを作成する必要があります。その後、必要に応じて穴を追加できます。最後に、画面にマスクを描画します。

Initialize the texture
Clear it to opaque black
Using the following blend states:
    D3DRS_SRCBLEND -> D3DBLEND_ZERO (hole's color does not matter)
    D3DRS_DESTBLEND -> D3DBLEND_ONE (preserve the black color)
    D3DRS_SRCBLENDALPHA -> D3DBLEND_ZERO
    D3DRS_DESTBLENDALPHA -> D3DBLEND_SRCALPHA
    D3DRS_SEPARATEALPHABLENDENABLE -> TRUE
Draw each hole sprite
Restore default blending (src_alpha / inv_src_alpha)
Render the texture as a sprite to the back buffer

上記のブレンド状態は、穴があるはずの場所が不透明であることを前提としています。次に、色は次のように計算されます。

blended color = 0 * hole sprite color + 1 * background color

これは常に黒でなければなりません。

また、アルファ チャネルは次のように計算されます。

blended alpha = 0 * hole sprite alpha + (1 - hole sprite alpha) * background alpha

ホール スプライトが不透明な場合、ブレンドされたアルファは 0 になります。透明な場合、ブレンドされたアルファは以前の値です。間の値がブレンドされます。

于 2013-07-30T17:50:59.350 に答える