J´ai vu un post récemment à propos de l´interface ID3DXSprite pour DX. Comme je n´était pas parvenu a obteni un résultat satisfaisant avec DX, j´avais pas mal abandonné l´idée. Aillant vu ce post ( merci au créateur, j´ai oublié de qui il s´agissait), j´ai pris en note le nom de l´interface afin de l´essayer ( je n´envisage pas de me lancer dans la 3D, trop de maths pour moi pour l´instant).
J´aurais une question venant d´un problème de compréhension sur un point qui, il me semble, est mal couvert par MSDN.
Pour faire un cycle complet de rendu, je dois faire ( où pd3dDevice est mon device de rendu, g_pd3dSprite un pointeur vers l´interface ID3DXSprite et g_pd3dTexture est un pointeur vers un interface de texture - il s´agit d´une liste pas d´une contextualisation dans un programme)
D3DXCreateSprite(g_pd3dDevice, &_pd3dSprite);
g_pd3dSprite->Begin(NULL); / / Ici j´ai laissé NULL n´étant pas trop certain du résultat qu´aurait les paramètres offerts
D3DXCreateTextureFromFile(g_pd3dDevice, " texture.jpg", &_pd3dTexture);
g_pd3dSprite->Draw(g_pd3dTexture, NULL, NULL, NULL, 0xFFFFFFFF); / / Encore la, beaucoup de NULL et de paramètre peu précis...
g_pd3dSprite->Flush(); / / Ou g_pd3dSprite->End();
Hors, ma question est la suivante:
Flush ramène le device de rendu à l´état où il était avant le Begin:
" Calls ID3DXSprite::Flush and restores the device state to how it was before ID3DXSprite::Begin was called."
Ne faudrait donc t´y pas refaire un begin à chaque rendu ? Parce que j´ai essayé de le faire, l´image apparait, tout semble bien aller, mais seul le premier begin, celui lors de l´initialisation du programme ( j´ai fait une fonction qui init. ma sprite) fonctionne ( j´ai loggé avec un if(FAILED(..)) ) ...
Juste pour ajouter que je suis bien au courant de l´existence de DirectDraw, SDL, d´Allegro, etc. Je ne veux pas faire de 3D mais j´aimerais quand même conserver le bénéfice d´une caméra qui peut se déplacer dans le monde ( ça évite d´avoir à programmer du scaling et ça permet des effets spéciaux même s´il ne peut y avoir de rotation dans tous les axes).
Hmmm comme je suis à la 3e page déjà, je bump la question ( je ne le referai pas, pas de panique
) .
Le post était de moi
Vu sue je m´en sert en ce moment voici un extrait de mon code de rendu simplifié :
g_peripherique3D->BeginScene();
g_peripherique3D->Clear( 0, NULL, D3DCLEAR_TARGET, 0x00FFFFFF, 0.0f, 0 ) ;
g_routineSprites->Begin();
g_routineSprites->Draw( image, SrcRect, Scaling, &3DXVECTOR2( ( float)rotationCenterY, ( float)rotationCenterY ) ,
Rotation, &3DXVECTOR2( ( float)x, ( float)y ) , 0xFFFFFFFF ) ;
g_routineSprites->End();
g_peripherique3D->EndScene();
g_peripherique3D->Present( NULL, NULL, NULL, NULL ) ;
Mais tu ne charges pas ton image ni ne crée la routine de sprite à chaques fois.
il FAUT faire un begin/end à chaque rendu, par contre tu ne dois PAS recréer ta texture à chaque fois.
pour le begin, tu peux laisser NULL mais sinon tu peux utiliser les paramètres pour plus de controle sur ce qu´effectue l´interface ( par exemple, activer l´alpha blending, tri auto des sprites par texture, etc.).
Pour le draw, la fonction est plus ou moins bugguée, passe le max de paramètres pour assurer que ça marche ( notamment la taille avec un RECT).
Evite de flusher au passage, c´est bon quand tu veux interrompre le rendu en cours pour substituer autre chose ( genre tes données ont changé, il faut quitter l´app en urgence, donc interrompre tous les trucs en cours, etc.)
Merci 1000x Lag-it et LGV,
Oui, je sais, faut pas charger la texture à chaque fois, je ne le fais qu´une fois dans ma procédure d´init de la sprite
.
J´ai changé quelques petites choses et ça ne fait plus d´erreur à chaque begin.
J´avais pas pris bonne note de la différence entre End et Flush, j´ai rectifié le tir pour ça
.
Merci encore
Après quelques tests, j´aurais quelques nouvelles questions...
1) Les textures doivent obligatoirement avoir un facteur de 2 ( du moins je pense que c´est le nom de cette règle... vous savez, 8, 16, 32, 64, 128, 256, 512, etc) ? J´ai fait une texture de 80x80 et elle est scalé de 1.6 pour atteindre 128x128...
2) Est-ce que le déplacement de la caméra a un effet sur les sprites ? J´avais espoir que cette interface amène un comportement similaire à un primitif ( un quad en fait) texturé. Ça ne semble pas être le cas, peut importe les valeurs que je mets dans *pEye de D3DXMatrixLookAtLH, la sprite ne bouge pas. De plus, j´ai essayé de transformer le sprite avec une matrice de translation:
D3DXMATRIX sprite_Transfo;
D3DXMatrixTranslation(&_Transfo , 85.0f , 85.0f , 0.0f);
g_pd3dSprite->SetTransform(&_Transfo);
Et dès que la valeur de Z est plus grande que 1, rien ne s´affiche ( aucun changement n´est visible pour une valeur entre 0 et 1).
1) Utilise D3DXCreateTextureFromFileEx pour utiliser une texture sns puissance de 2, voici un exemple de code simplifié :
LPDIRECT3DTEXTURE9 image;
D3DXIMAGE_INFO imageInfo;
ZeroMemory(&, sizeof(D3DXIMAGE_INFO));
HRESULT hr;
if( FAILED( hr = D3DXGetImageInfoFromFile( fileName, & ) ) )
{
DXTrace(__FILE__, __LINE__, hr, fileName, true);
}
largeur = imageInfo.Width;
hauteur = imageInfo.Height;
hr = D3DXCreateTextureFromFileEx( g_peripherique3D,
fileName,
imageInfo.Width,
imageInfo.Height,
1,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_DEFAULT,
D3DX_DEFAULT,
colorKey,
&,
NULL,
&
);
2) Personnelemnt je me sers de ces sprites comme de vrais sprites : pas de matrices de transformations 3d pour moi, j´utilise un simple vecteur 2d pour représenter leurs coordonnées.
De plus, le clipping est géré par DirectX.
Donc je me simplifie la vie ![]()
Bon vire les 2 lignes :
largeur = imageInfo.Width;
hauteur = imageInfo.Height; ![]()
Merci encore une fois !
Je suppose que ton appli n´a pas besoin de redimensionner ( grandir, réduir) les sprites ? J´avais en tête de pouvoir le faire avec une matrice de translation... mais c´est pas le cas
. Je me vois plutôt mal écrire un scaler pour les textures
.
Sisi, ma routine fais des agrandissements, des rotations etc..
Mais tou est géré à l´affichage :
g_routineSprites->Draw( Image, SrcRect, Scaling, CentreRotation ,
Angle, Coords , Couleur ) ;
Avec LPDIRECT3DXSPRITE, raisonne en 2d et non plus en 3d plane ![]()
Pas ma routine, la routine dsl.
Mais cela simplifie réellement les choses : exits les matrices qui sont très lourdes quand on veut faire un simple menu ou un petit jeu 2d ![]()
j´allais dire la meme chose
bien pratique cette méthode Draw, qui prend tout en charge !
Au passage, derrière l´interface ID3DXSPRITE ce sont bien des quads texturés, mais l´interface englobe un peu plus que cela, et masque pas mal des comportements de D3D normaux, c´est d´ailleurs pourquoi les manips sur les matrices habituelles ne donnent rien avec les sprites.
En théorie, tu te fais une petite classe pour encapsuler les infos nécessaire à faire tes ID3DXSPRITE->Draw(), avec les infos attendues, histoire de rendre encore un peu plus transparent la chose, et ensuite tu dois pouvoir avancer rapidement
Ceci dit c´est assez simple et puissant, mais si tu cherches encore plus puissant, jettes un oeil à :
http://jpeglauden.free.fr/documents/directx/Cours%20DGraphics.zip
( Perso, LPDIRECT3DXSPRITE me suffit amplement )
Merci tlm ( encore et encore
) !
Je fonce encore dans un mur
g_routineSprites->Draw(Image, SrcRect, Scaling, CentreRotation, Angle, Coords, Couleur);
7 paramètres ? Est-ce que g_routineSprites est un LPD3DXSPRITE ? Parce que vue d´msdn...
HRESULT Draw(
LPDIRECT3DTEXTURE9 pTexture,
CONST RECT *pSrcRect,
CONST D3DXVECTOR3 *pCenter,
CONST D3DXVECTOR3 *pPosition,
D3DCOLOR Color
) ;
Désolé d´avoir autant de questions, ça devient gênant
mais merci de vos réponses, c´est apprécié.
oui effectivement, il n´y a que 5 paramètres ; c´est p-e un vieux proto qui est dans la doc :-?
pour la rotation et le scaling, qui ne sont pas dans cette version, tu peux utiliser ID3DXSPRITE->SetTransform() qui prend une D3DXMATRIX standard.
Oui g_routineSprites est un LPD3DXSPRITE.
Oui oui, 7 paramètre ![]()
Dans l´odre :
1) Ta texture ( objet ( LP)DIRECT3DTEXTURE9 )
2) La région de cette texture à afficher : par exemple, tu crée tout une texture avec les 50 positions différentes de ton héro et tu n´en affichera qu´une seule en lui passant le rectangle qui la contient.
3) Les donnéees d´agrandissement en x et y : pour étirer ou comprimer ton sprite à l´affichage ( ne modifie pas l´original bien sûr )
4) Ton centre de rotation ( si tu veux faire des rotations. C´est le coin en haut à gauche par défaut ) ( ne modifie pas l´original bien sûr )
5) Ton angle de rotation.
6) Les coordonnées x et y d´affichage de ton sprite
7) Une clé de couleur pour appliquer des effets de couleurs ( ca n´est pas la clé de transparence ! ) .
Alors 7 paramètres, certes, mais c´est puissant
De rien, c´est tout aussi apprécié d´aider ![]()
C´est pas une vieille version que tu as là ?
Moi j´utilise DirectX 9.0 b...
ben pareil :/ le 9.0b Summer Update 2003
et je n´ai bien aussi qu´une version à 5 params ; bah, au pire c´est pas dur de refaire ta fonction à 7 en cumulant un settransform et un draw, mais c´est bizarre cela dit
Dernière révision du SDK de DirectX 9.0b
heum... un lien...
http://www.microsoft.com/downloads/details.aspx?FamilyId=9216652F-51E0-402E-B7B5-FEB68D00F298&displaylang=en
C´est ce que j´ai d´installé.
Je sais pas si c´est un vieux proto à 5 paramètres qui est encore dans la doc mais il fonctionne ( à tout le moins je peux afficher une image).
J´ai essayé un SetTransform en faisant une matrice de translation, ça ne fonctionne pas ( la sprite bouge mais ne grossie pas). Je pense me souvenir que j´utilisais D3DXMATRIXA16 et non pas D3DXMATRIX, le problème vient p-e de là... ou sinon c´est la mauvaise transformation. Je vais refaire le tour de mes travaux voir ce que j´arrive à faire avec tout ça, merci beaucoup encore une fois.