We got a global graphics class that each object can reach and use in their draw functions. It looks like this:
class Graphics
{
public:
// Draws a texture
void drawTexture(IDirect3DTexture9 *texture, float x, float y, int width, int height, float rotation = 0);
private:
// Buffer for vertices of the type TextureVertex
IDirect3DVertexBuffer9* mVB_texture;
}
Graphics::drawTexture(...) looks like this:
void Graphics::drawTexture(IDirect3DTexture9 *texture, float x, float y, int width, int height, float rotation)
{
// Texture coordinates range from 0-1, 0 is the most left and 1 the most right in the X direction for example
Rect drawRect;
drawRect.left = x-(width/2);
drawRect.right = x+(width/2);
drawRect.top = y-(height/2);
drawRect.bottom = y+(height/2);
gd3dDevice->SetVertexDeclaration(TextureVertex::Decl);
gd3dDevice->SetStreamSource(0, mVB_texture, 0, sizeof(TextureVertex));
TextureVertex *vertices = 0;
mVB_texture->Lock(0, 0, (void**)&vertices, 0);
// Setup vertices
vertices[0].pos.x = (float) drawRect.left;
vertices[0].pos.y = (float) drawRect.top;
vertices[0].pos.z = 0;
vertices[0].tex0.x = 0.0f;
vertices[0].tex0.y = 0.0f;
vertices[1].pos.x = (float) drawRect.right;
vertices[1].pos.y = (float) drawRect.top;
vertices[1].pos.z = 0;
vertices[1].tex0.x = 1.0f;
vertices[1].tex0.y = 0.0f;
vertices[2].pos.x = (float) drawRect.right;
vertices[2].pos.y = (float) drawRect.bottom;
vertices[2].pos.z = 0;
vertices[2].tex0.x = 1.0f;
vertices[2].tex0.y = 1.0f;
vertices[3].pos.x = (float) drawRect.left;
vertices[3].pos.y = (float) drawRect.bottom;
vertices[3].pos.z = 0;
vertices[3].tex0.x = 0.0f;
vertices[3].tex0.y = 1.0f;
// Unlock the vertex buffer
mVB_texture->Unlock();
// Set texture
gd3dDevice->SetTexture (0, texture);
// Draw content in buffer
gd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
gd3dDevice->SetTexture (0, NULL);
}
An example when using drawTexture(...) :
Player::draw()
{
gGraphics->drawTexture(getTexture(), getX(), getY(), getWidth(), getHeight());
}
So we basicly uses the same vertex buffer for every object in the game and just change it's vertex attributes. It seems like all the calls to the Lock(...) and Unlock() functions is one of the reasons to the slow down.
We've thought about each object having their own vertex buffer and only change it when the object moves, scales or rotates. Is that a viable way to do it?
What's your opinion about our solution? What can we change and how would you write an efficient drawing algorithm?
Cheers