2013-07-30 7 views
3

Я работаю на игру, используя DirectX 9. Вот что я пытаюсь сделать:DirectX альфа маскирования

После того, как сцена оказывается, на нем я хочу сделать несколько спрайтов: черная крышка на всей сцене и несколько спрайтов, которые являются масками, показывающими, где на крышке должны быть отверстия. До сих пор я пытался испортить режим смешивания, но не повезло. установка Мой кода это выглядит так:

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 

После ответа Нико Schertler, вот код, который я придумал:

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(); 

Unfortunatelly, происходит сбой приложения при восстановлении старой цели визуализации. Любой совет?

+0

Какая ошибка у вас возникла? Кстати, вы должны использовать формат текстуры с альфа-каналом, конечно. –

+0

Точка обнаружения нарушения доступа 0xcdcdcdcd. Указатель pBackBuffer выглядит нормально до точки, где я обрабатываю спрайты, а затем в D3DD-> SetRenderTarget (0, pBackBuffer) его значение отличается (всегда 0xcdcdcdcd). –

+0

Также я изменил формат текстуры на D3DFMT_A8R8G8B8 –

ответ

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. Когда он прозрачен, смешанный альфа предыдущим значения. Значения между ними смешиваются.