The correct way to get the Direct3D Device

Started by
12 comments, last by lukesmith123 12 years, 4 months ago
Previously I had been overloading functions in my classes for example, SetDevice(LPDIRECT3DDEVICE9 dev) to pass the Direct3D Device to the class.

Is this a bad way of getting access to the class?

Would a better method be to create a singleton of a rendermanager that is passed the Direct3D device and has a static function get() so that classes can just call RenderManager.Get().Device when they need access to the device?

Would this be a more correct method?

thanks,
Advertisement

Previously I had been overloading functions in my classes for example, SetDevice(LPDIRECT3DDEVICE9 dev) to pass the Direct3D Device to the class.
Can you post some example code of what you mean?
Why do these classes need access to the D3D device anyway?
Would a better method be to create a singleton of a rendermanager[/quote]No!


LPDIRECT3DDEVICE9 device;

void StaticMesh::SetDevice(LPDIRECT3DDEVICE9 dev)
{

device = dev;

}



This is what I had been doing to pass the device to a class that needed it.

A class that needs access to it is for example, StaticMesh class that needs access to the the D3D device when calling the function D3DXLoadMeshFromX(). Or the game class needing to set the renderstate.

I am passing in the address of the device however I read someones code that worked in the same way and he had a comment above it saying that this was a bad way of doing things.

I thought the rendermanager singleton route was fairly common?
Is this method wrong?

How are you guys doing it?

This is what I had been doing to pass the device to a class that needed it.

A class that needs access to it is for example, StaticMesh class that needs access to the the D3D device when calling the function D3DXLoadMeshFromX(). Or the game class needing to set the renderstate.

I am passing in the address of the device however I read someones code that worked in the same way and he had a comment above it saying that this was a bad way of doing things.

What would happen if you didn't call setDevice? Does it make sense for an instance of StaticMesh to exist without reference to a D3D device?

I'm anticipating that StaticMesh has a dependency on the device right from the off. Generally all dependencies should be provided to an object via its constructor rather than through setter methods.

I thought the rendermanager singleton route was fairly common?[/quote]
Unfortunately it is, but don't confuse it being common with it being good practice.

Yeah because StaticMesh for example needs to call D3DX functions which require the device as input.

I didnt do this in the constructor because I didnt want to create the objects dynamically because I was worried about fragmentation and things like that.

Is it acceptable to have a setter method in this case or should all the objects be created dynamically?
A class that needs access to it is for example, StaticMesh class that needs access to the the D3D device when calling the function D3DXLoadMeshFromX(). Or the game class needing to set the renderstate.
I would try to redesign things so that less classes need the device in the first place. If lots of different parts of your game need the device, then your rendering code is spaghetti spread through the entire code base. You should try to collect all that spaghetti and put it into a renderer class.

The game class really should not be setting any render-states. If everything is allowed to use the device, how can you easily reason about what state the device is in at any point in time? If you've got a single renderer that is responsible for the device, then it's easier to know, for example, which textures are bound or whether alpha blending is on or off.

If you don't want to add the device to the meshes constructor, because you want to be able to make an instance of a mesh object without actually loading a mesh, then you should instead add the device to the load function.class Mesh { public:
void Load(LPDIRECT3DDEVICE9 dev, const char* file) { D3DXLoadMeshFromX(file, dev, &mesh); }
bool Loaded() const { return mesh!=0; }
private:
LPD3DXMESH mesh;
};
Yeah good points thanks.

I would like to redesign things so that less classes need the device in the first place but I cant think how I could do this, for example with the StaticMesh class the functions D3DXCreateMeshFromX is called which needs the device.

I cant think of any way I could redesign it?

Could you explain the thing about a single renderer. At the moment I have a game class which creates all the objects and then calls their initialization update, draw functions.

thanks so much for the advice.
for example with the StaticMesh class the functions D3DXCreateMeshFromX is called which needs the device.
One possibility is to make it so that meshes don't call D3DXCreateMeshFromX at all - you could move this responsibility into a factory class, which is owned by the device.
class Mesh
{
private:
friend class MeshFactory;
Mesh( LPD3DXMESH m ) : mesh(m) {}
LPD3DXMESH mesh;
}
class MeshFactory
{
public:
Mesh* Create( LPDIRECT3DDEVICE9 device, const char* file )
{
LPD3DXMESH d3dMesh = 0;
D3DXLoadMeshFromX(file, dev, &d3dMesh);
return new Mesh( d3dMesh );
}
};
class GfxDevice
{
public:
Mesh* CreateMesh( const char* filename ) { return meshFactory.Create( device, filename ); }
private:
LPDIRECT3DDEVICE9 device;
MeshFactory meshFactory;
};


Could you explain the thing about a single renderer. At the moment I have a game class which creates all the objects and then calls their initialization update, draw functions.[/quote]Many of the games that I've worked on have worked in a way where when a game object "draws" itself, it doesn't actually draw anything right there and then -- instead, it collects up all the models that make up the game object (which is a mesh/texture/shader/material/etc bundle) and puts them into a list. Later on, the renderer consumes the whole list at once and calls the actual D3D functions that are required to draw those meshes.
This way, game objects don't know about D3D at all, they just are built out of "models", and know how to pass those models to the renderer.void Game::Draw( Renderer& renderer )
{
std::vector<Model*> submissionList ;
m_player.Draw( submissionList );
renderer.Submit( submissionList );
}
void Player::Draw( std::vector<Model*>& list )
{
list.push_back( &m_body );
list.push_back( &m_weapon );
}
void Renderer::Submit( std::vector<Model*>& list )
{
for each model
call d3d commands required to draw the model
}
Thats fantastic thanks so much for explaining this. So the Renderer creates the GfxDevice privately and then creates and renders any D3D meshes, textures etc and renderers them.


So when combining these two techniques, what would we actually be passing to the renderer in the list?

would it be a seperate class that just contained things like the position and the filename as public members?


also in the Renderer::Submit function would we be creating a new instance of Mesh and rendering it each time for each object?

for example Mesh mesh = gfxDevice.CreateMesh(model.filename)

This topic is closed to new replies.

Advertisement