Texture Management

Started by
6 comments, last by Pedigree_D 14 years, 10 months ago
Hi guys, Im having problems with how to handle textures in DirectX. Im trying to find the most efficient way to manage IDirect3DDTexture9 pointers. Im using sprites and currently im putting together a framework to which i can create games without having to code window creation, direct3d initialization etc over and over. When it comes the textures im wondering whether to have a class that encapsulates sprite and texture creation...


typedef D3DXVECTOR3 VECTOR;

class SPRITE
{
public:
   SPRITE();
   ~SPRITE();

   void LoadTexture(const char* filename);
   HRESULT DrawSprite(VECTOR* pos, int frame);

private:
   ID3DXSprite* sprite;
   IDirect3DTexture9* tex;

};

// Used as:
// SPRITE character;
VECTOR pos(100.0f, 100.0f, 0.0f);
// character.LoadTexture("test.png");
// character.DrawSprite(&pos, 1);


Above is what i would assume it would look like of the top of my head. Now, would it be ideal this way or would it be best to have the ID3DXSprite pointer in with the rendering code as it has to be created once with D3DXCreareSprite() and pass it to the constructor of a SPRITE object?? I have been advised to use a list of IDirect3DTexture9 pointers by other people but the problem i have with this is searching for the specific texture you want to draw. How would you guys do it?? Thanks
Advertisement
Don't fully understand your question, but I hope this helps. This is the SPRITE class I made:

VECTOR nVector(float X, float Y); // new vectorclass SPRITE {	public:		float x, y;		SPRITE() {			D3DXCreateSprite(_dev, &sprite);		}		void LoadTexture(const char* Path) {			D3DXCreateTextureFromFile(_dev, Path, &tex);		}		void Draw(VECTOR Position, VECTOR Center, COLOR Color) {			_dev->BeginScene();			sprite->Begin(D3DXSPRITE_ALPHABLEND);			sprite->Draw(tex, NULL, &D3DXVECTOR3(Center.x, Center.y, 0),				&D3DXVECTOR3(Position.x, Position.y, 0),				D3DCOLOR_XRGB(Color.R, Color.G, Color.B));			sprite->End();			_dev->EndScene();			_dev->Present(NULL, NULL, NULL, NULL);			x=Position.x;			y=Position.y;		}		void Draw() {			_dev->BeginScene();			sprite->Begin(D3DXSPRITE_ALPHABLEND);			sprite->Draw(tex, NULL, &D3DXVECTOR3(0, 0, 0),				&D3DXVECTOR3(x, y, 0),				D3DCOLOR_XRGB(255, 255, 255));			sprite->End();			_dev->EndScene();			_dev->Present(NULL, NULL, NULL, NULL);		}		void Release() {			if (sprite)				this->sprite->Release();			sprite=0;			if (tex)				this->tex->Release();			tex=0;		}	private:		LPD3DXSPRITE sprite;		LPDIRECT3DTEXTURE9 tex;};


Note: LPD3DXSPRITE is the same as ID3DXSprite* and LPDIRECT3DTEXTURE9 is the same as IDirect3DTexture9*. _dev is the global LPDIRECT3DDEVICE9 I use.
Ideally you have a single ID3DXSprite object and run all rendering through that. MUCH more efficient than having each Sprite object own a ID3DXSprite of it's own.


-Nate S.
"Always forgive your enemies, nothing annoys them more.."
Hi,

Here's the implementation of my Sprite class.
I'm managing all the elements over only one sprite.

typedef struct _SPRITE_ELEMENT{   LPDIRECT3DTEXTURE9 Texture;   D3DXMATRIX         TransformationMatrix;   std::string        Name;} SPRITE_ELEMENT;typedef std::vector <SPRITE_ELEMENT> CSpriteVector;class CSprite{   CSprite () {m_pSprite = NULL;};   CSprite (LPDIRECT3DDEVICE9 pDev) {D3DXCreateSprite (pDev, &m_pSprite);}   ~CSprite() {if (m_pSprite) m_pSprite->Release();}   SPRITE_ELEMENT*   Sprite  (std::string name); //returns the element "name"   SPRITE_EMEMENT*   Sprite  (UINT i); //returns (i)th element   HRESULT   Begin (DWORD options = 0)   {       if (!m_pSprite) return E_FAIL;       return m_pSprite->Begin (options);   }   HRESULT   End    ()    {       if (!m_pSprite) return E_FAIL;       return m_pSprite->End ();   }   HRESULT   Draw    (UINT i) //draws only (i)th element   {       if (m_pSprite == NULL) return E_FAIL;       if (Sprite (i) == NULL) return E_FAIL;       m_pSprite->SetTransform (&Sprite(i)->TransformationMatrix);       m_pSprite->Draw (Sprite(i)->Texture, NULL, NULL, NULL, 0xFFFFFFFF);       //passing three NULLs because we use transformation matrix   }   HRESULT   Draw    (); //draws all the elements with a for() loop      LPD3DXSPRITE  m_pSprite;   CSpriteVector m_vSpriteArray;};


You can build a transformation matrix by using D3DXTransformation2D () function.

Hope this helps.

[Edited by - programci_84 on June 21, 2009 4:09:11 PM]
There's no "hard", and "the impossible" takes just a little time.
You don't want your sprite class to load up the texture itself. If you got 20 of the same sprites then you have 20 copies of the the texture in memory. You should have some kind of texture manager class that handles the actual loading into memory and when another sprite is created it just gets a pointer to the original instead of loading another into memory. As for drawing, your render function should take a pointer to a previously created ID3DXSprite and use that to render instead of every sprite having its own. Each sprite calling its own Begin()/End() is going to slow things down.

Little pseudo code:

class Sprite{public:     Sprite(Vec2 pos, IDirect3DTexture9 *tex) : m_pos(pos), m_tex(tex) {};     Draw(ID3DXSprite *sprite) {sprite->Draw(m_tex,...,m_pos....);};private:     Vec2 m_pos;     IDirect3DTexture9 *m_tex;};

Wow, thanks for all the replies. Sorry i wasn't as quick with me response i've been having some issues with my laptop, seems Vista has decided my copy isn't genuine when it was pre-installed when i bought it?? Anyway, programci_84, that was what i was thinking of myself. The only problem i had was searching for the element in the vector i wish to draw by name. I use STL vector to handle my states but i haven't really plunged into the depths of vectors. Anyone have any good resources on the standard template library??

Thanks
Hi,

Quote:The only problem i had was searching for the element in the vector i wish to draw by name.

It's quite simple. You know there's a Name member in my SPRITE_ELEMENT declaration. Here's the snippet how I get the element called "Name":
SPRITE_ELEMENT* Sprite (std::string Name){   for (UINT i = 0; i < m_vSpriteArray.size(); i++)   {      if (m_vSpriteArray.Name == Name)          return &m_vSpriteArray;   }   return NULL;}


Also, here's an STL tutorial page. This is a Linux related website but this is not important for you.
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

Hope this helps.
Rohat.
There's no "hard", and "the impossible" takes just a little time.
That helps alot programci_84!! Exactly what i was looking for :)

This topic is closed to new replies.

Advertisement