The Alpha operationsAs Direct3D renders a scene, it can integrate color information from several sources: vertex color, the current material, texture map and the color previously written to the render target. It can blend several of these colors. A factor called alpha, which could be stored in vertices, materials and texture maps, can be used to indicate how blending should be weighted. An alpha value of 0 means full transparency, an alpha value of 1 means some level of semitransparency. Modulate AlphaIn 1992 I played Comanche from Novalogic the first time. I wondered about making the night flight feature in some missions. The whole terrain, the clouds and the horizon were green. They looked like modulating a green ambient light with the textures by alpha. For this example, I switched from a directional light to a green ambient light. This light is modulated with the texture colour:
#if TM != MODULATEALPHA
// Set up the light
if (m_pDeviceInfo->ddDeviceDesc.dwVertexProcessingCaps
& D3DVTXPCAPS_DIRECTIONALLIGHTS)
{
D3DLIGHT7 light;
D3DUtil_InitLight(light, D3DLIGHT_DIRECTIONAL, 0.0f, -0.4f, 1.0f );
m_pd3dDevice->SetLight(0, &light );
m_pd3dDevice->LightEnable(0, TRUE );
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, TRUE );
}
#else
// Set the ambient light.
D3DCOLOR d3dclrAmbientLightColor = D3DRGBA(0.0f,1.0f,0.0f,1.0f);
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, d3dclrAmbientLightColor);
#endif
To modulate the ambient color with the texture:
#elif TM == MODULATEALPHA
m_pd3dDevice->SetTexture(0, D3DTextr_GetSurface("wall.bmp"));
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
...
Alpha blending with the Frame BufferYou can use alpha blending to combine the primitive's color with the color previously stored in that pixel of the frame buffer. That's called blending with the frame buffer. Using this form of alpha blending, you can simulate semitransparent objects, combine two images, and add special effects such as force fields, flames, plasma beams and light mapping. Direct3D uses the following formula to compute the final color for each pixel in the rendered primitive: FinalColor = SourcePixelColor * SourceBlendFactor + DestPixelColor * DestBlendFactor It lets you change the SourceBlendFactor and DestBlendFactor flags to generate the effect you want. I set the following RenderStates in InitDeviceObjects():
...
#if TM == BLENDWFRAME
m_pd3dDevice->SetRenderState (D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
// Set the source blend state.
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR);
// Set the destination blend state.
m_pd3dDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);
#endif
...
As a result of the calls in the preceding code fragment, Direct3D performs a linear blend between the source color (the color of the primitive being rendered at the current location) and the destination color (the color at the current location in the frame buffer). This gives an appearance similar to tinted glass. Some of the color of the destination object seems to be transmitted through the source object. The rest of it appears to be absorbed. Alpha blending requires a fair bit of extra math and memory access, so turning it on and off with ALPHABLENDENABLE is worth the effort. In the Render() method, there's only a call to set the texture:
...
#elif TM == BLENDWFRAME
m_pd3dDevice->SetTexture(0, D3DTextr_GetSurface("wall.bmp"));
#endif
...
I hope you enjoyed our small trip into the word of the Direct3D 7 IM Framework. If you disliked or liked it, give me a sign at wolf@direct3d.net.
|