Le billboard

Ici on va créer les feux produits par les turbines des modules. Pour cela on placera dans le monde une image sur un plan auquel on lui associe une couleur clé. On prendra le noir, ce qui signifie que tous les pixels de couleur noir ne seront pas affichés. En clair, plus la couleur est foncée, et plus il y aura d'effet de transparence.
On commence par charger la texture du fichier dans le pointeur de type LPDIRECT3DTEXTURE9.
Ensuite on crée le vertexbuffer qui recevra les 4 vertices du plan. en précisant qu'il s'agit d'un FVF (flexible vertex format). Notre image ne sera pas dépendante de la lumière projetée dans le monde et diffusera sa propre lumière, d'où le D3DFVF_DIFFUSE. Le drapeau D3DFVF_TEX1 permet d'indiquer qu'on utilisera le système de texture U, V. Ce qui permet de recadrer la texture sur le plan en utilisant les coefficiants allant de 0 à 1.
Ensuite pour créer les vertices il nous faut verrouiller DirectVertexBuffer.

vertices.cpp

#include "vertices.h"
#include "decl_vertices.h"

HRESULT init_vertices(LPDIRECT3DDEVICE9 *_obj_Direct3DDevice, LPDIRECT3DVERTEXBUFFER9 *_obj_DirectVB, LPDIRECT3DTEXTURE9 *pTexture, const char *nom, float lng, float larg) {

HRESULT hr;

if( FAILED( D3DXCreateTextureFromFile(*_obj_Direct3DDevice, nom, pTexture ) ) )
return E_FAIL;

hr = (*_obj_Direct3DDevice)->CreateVertexBuffer( 4 * sizeof(VERTICES), 0, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, D3DPOOL_DEFAULT, _obj_DirectVB, NULL);
if (FAILED(hr)) return E_FAIL;

VERTICES* pVertices;

hr = (*_obj_DirectVB)->Lock( 0, 0, (void**)&pVertices, 0);
if(FAILED(hr)) return E_FAIL;

pVertices[0].v = D3DXVECTOR3( -larg/2, -lng/2, 0);
pVertices[0].couleur = 0xffffffff;
pVertices[0].tu = 0;
pVertices[0].tv = 0;
pVertices[1].v = D3DXVECTOR3( -larg/2, lng/2, 0);
pVertices[1].couleur = 0xffffffff;
pVertices[1].tu = 0;
pVertices[1].tv = 1;
pVertices[2].v = D3DXVECTOR3( larg/2, -lng/2, 0);
pVertices[2].couleur = 0xffffffff;
pVertices[2].tu = 1;
pVertices[2].tv = 0;
pVertices[3].v = D3DXVECTOR3( larg/2, lng/2, 0);
pVertices[3].couleur = 0xffffffff;
pVertices[3].tu = 1;
pVertices[3].tv = 1;

(*_obj_DirectVB)->Unlock();

return S_OK;
}

vertices.h

#include <d3dx9tex.h>
#include <d3d9.h>

// pointeur sur direct3Dvertexbuffer
static LPDIRECT3DVERTEXBUFFER9 obj_DirectVB, obj_DirectVB2;

// pointeur sur texture
static LPDIRECT3DTEXTURE9 obj_texture, obj_texture2;

struct VERTICES
{
D3DXVECTOR3 v; 
D3DCOLOR couleur; 
FLOAT tu, tv;
};

decl_vertices.h

HRESULT init_vertices(LPDIRECT3DDEVICE9*, LPDIRECT3DVERTEXBUFFER9*, LPDIRECT3DTEXTURE9*, float, float);

La fonction rendu doit prendre en compte deux nouveaux paramètres :

VOID Rendu(HWND hWnd, unsigned int param, LPDIRECT3DDEVICE9 *D3DD, LPDIRECT3DTEXTURE9 *pText, LPDIRECT3DVERTEXBUFFER9 *pVB, _module_ *rp, _module_ *rp2, _mesh_ *mtm_modulea, _mesh_ *mtm_laby, _mesh_ *mtm_missile, _mesh_ *mtm_moduleb, _mesh_ *mtm_coeur, clavier *etm)
{

On commence par retirer la lumière de la scène, puisque le plan n'aura pas d'interaction avec.
Ensuite on crée l'effet Alpha de transparence.

D3DRS_ALPHABLENDENABLE : permet d'effectuer un test sur les pixels pour effectuer l'effet alpha.
D3DRS_SRCBLEND, D3DRS_DESTBLEND : permet d'indiquer qu'il faut mélanger les pixels alpha du plan aux autres pixels.

On associe ensuite le buffer vertex à Direct Device, puis on indique à DirectDevice le type de vertices comme FVF et on associe la texture.

rp2->monde._41=vx*cos(rp->module_rot)+vz*sin(rp->module_rot);
rp2->monde._43=-vx*sin(rp->module_rot)+vz*cos(rp->module_rot);

rotation_Y(&rp2->monde, rp->module_rot - cell2->t_rot);

projection(&rp2->monde, &(*D3DD));

obj2device_dessin_mesh(mtm_missile->nbr_de_mat, mtm_missile, &(*D3DD), &mtm_missile->obj_mesh);

cell2 = cell2->suivant;
}

(*D3DD)->SetRenderState( D3DRS_LIGHTING, FALSE );

(*D3DD)->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
(*D3DD)->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
(*D3DD)->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);

(*D3DD)->SetStreamSource( 0, *pVB, 0, sizeof(VERTICES) );
(*D3DD)->SetFVF( D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1 );
(*D3DD)->SetTexture( 0, *pText);

Lorsque le module tourne il faut que le feu arrière puisse suivre, on le place donc sur le cercle de centre (0, 0, 0) sans effectuer de rotation sur lui même puisqu'il faut que le plan soit toujours face à la caméra pour un meilleur effet. On fait revenir le hallo vers la caméra lorsque le module tourne pour éviter que le plan ne s'interpose avec celui-ci. Suivant qu'on tourne à gauche ou à droite l'ordre d'affichage des deux hallos gauche et droit est à prendre en compte.

if(rp->rot_cam>0) {

rp->monde._41 = _A_ * cos(_fi_+rp->rot_cam/4);
rp->monde._43 = _A_ * sin(_fi_+rp->rot_cam/4) - rp->rot_cam/2;
rp->monde._13 = rp->monde._31 = 0.0f;
rp->monde._11 = rp->monde._22 = rp->monde._33 = rp->coef_vitesse_module * .1f;

projection(&rp->monde, &(*D3DD));
(*D3DD)->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

rp->monde._41 = -_A_ * cos(_fi_-rp->rot_cam/4);
rp->monde._43 = _A_ * sin(_fi_-rp->rot_cam/4) - rp->rot_cam/1.5;
rp->monde._13 = rp->monde._31 = 0.0f;
rp->monde._11 = rp->monde._22 = rp->monde._33 = rp->coef_vitesse_module * .1f;

projection(&rp->monde, &(*D3DD));
(*D3DD)->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
}
else {

rp->monde._41 = -_A_ * cos(_fi_-rp->rot_cam/4);
rp->monde._43 = _A_ * sin(_fi_-rp->rot_cam/4) + rp->rot_cam/2;
rp->monde._13 = rp->monde._31 = 0.0f;
rp->monde._11 = rp->monde._22 = rp->monde._33 = rp->coef_vitesse_module * .1f;

projection(&rp->monde, &(*D3DD));
(*D3DD)->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

rp->monde._41 = _A_ * cos(_fi_+rp->rot_cam/4);
rp->monde._43 = _A_ * sin(_fi_+rp->rot_cam/4) + rp->rot_cam/1.5;
rp->monde._13 = rp->monde._31 = 0.0f;
rp->monde._11 = rp->monde._22 = rp->monde._33 = rp->coef_vitesse_module * .1f;

projection(&rp->monde, &(*D3DD));
(*D3DD)->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

}

rp->monde._11 = rp->monde._22 = rp->monde._33 = 1.0f;

(*D3DD)->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
(*D3DD)->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
(*D3DD)->SetRenderState( D3DRS_LIGHTING, TRUE );

// fin de la scène
(*D3DD)->EndScene();

// affiche le back buffer à l'écran
(*D3DD)->Present(NULL, NULL, NULL, NULL);

Dans la fonction main on aura :

for(i = 0; i < NBR_SNDS; i++)
if(LoadDirectSound(&obj_DirectSound, &(DSbuffer[i]), chemin_wav[i]) != S_OK)
return -1;

init_vertices(&obj_Direct3DDevice, &obj_DirectVB, &obj_texture, "glow.bmp", 20, 20);
init_vertices(&obj_Direct3DDevice2, &obj_DirectVB2, &obj_texture2, "glow.bmp", 20, 20);
...
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else {
Rendu(hCtrl_2, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, &obj_Direct3DDevice,
&obj_texture, &obj_DirectVB, module1, module2, mtm[0], mtm[4], mtm[6], mtm[2], mtm[8], &et_module);
Rendu(hCtrl_1, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, &obj_Direct3DDevice2,
&obj_texture2, &obj_DirectVB2, module2, module1, mtm[3], mtm[5], mtm[7], mtm[1], mtm[9], &et_module2);
}
}


Téléchargez la source, cliquez ci-dessous :