Loading Shaders for multiple models

Started by
9 comments, last by lukesmith123 12 years, 8 months ago
When using a shader .fx file for multiple models do I need to load it each time for each models. For instance in my custom model class load the shader and render the model with that shader rather than loading the shader once in my main class and then render each model with the one effect? I tried doing the latter and I had a problem because the world matrix for each model is different.

Also how does all of this relate to the ppEffectInstances argument of the D3DXLoadMeshFromX function?
Advertisement
You don't need to load an effect for each model if you don't want to. However you will need to set all per-mesh parameters (like textures, material colors, etc.) each time you use that effect to render a model. If you create multiple effects (or clone an effect for each mesh) then you can set those per-mesh and per-material parameters once at load time.

As far as the EffectInstances stuff, an X file has the capability to store data indicating a .fx file to use for a material as well as a bunch of properties to set onto that effect. So for instance if you had a diffuse color property, it will have a D3DXEFFECTDEFAULT containing the name "DiffuseColor" and 3 or 4 floats representing the actual value. Then when you load the effect, you can set the value of those parameters to the value in the .X file. However most .X files don't have this information and will just have the "standard" material data instead (the stuff you get in the D3DXMATERIAL buffer).
The thing is when I just load one effect and try to use it for all my models, each model is rendered at the world position of the last model in the list.

What I'm doing is making a function in my model class for SetShader(Shader shader); so I can make create the shader in my main class and pass in the shader to each of my models.

So in the model update function I pass in the view and projection and set the world view and projection parameters.

Then in the models draw function, before and after the drawsubset function is called I call Begin and end functions of my shader which has the effects Begin() and BeginPass() and End() / EndPass() functions.

Any Idea what I'm doing wrong here?




The thing is when I just load one effect and try to use it for all my models, each model is rendered at the world position of the last model in the list.


then for each model set the model dependant data IE
set the texture
set the world matrix
set light
etc

problem gone.
:) :) :)

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

EDIT:

Yeah I was doing that, It seems my problem was because I was trying to set things like position of my models before adding them to a std::list but I need to go through the list and set the the positions and stuff afterwards.

Sorry I thought I had figured this out but I hadnt.

All the models are using the last model in the lists world matrix.

Im passing the the shader to each of my models in a setShader function.

Then in the relevant functions in the model class the parameters are set.

and in my game class I loop through the list of models and call the functions.

Ive tried putting the models in an array as well and I have the same problem.

I presume it would be a huge waste of memory to create a new shader instance for each model if say I had 100 models.

note also that I'm using directX 9

Please help! thanks.

Are you setting the parameters before you call Begin on the effect?
Yeah.
Ok so I guess I need to post some code. Ive taken out some bits that arent relevant to try to keep the size down.

This is from Model class,

void Model::Update(D3DXMATRIX mView, D3DXMATRIX mProjection, Shader s)
{
D3DXMATRIX matScale;
D3DXMATRIX matRotateX;
D3DXMATRIX matRotateY;
D3DXMATRIX matRotateZ;
D3DXMATRIX matTranslate;

D3DXMatrixScaling(&matScale,scale.x,scale.y,scale.z);
D3DXMatrixRotationX(&matRotateX,D3DXToRadian(rotation.x));
D3DXMatrixRotationY(&matRotateY,D3DXToRadian(rotation.y));
D3DXMatrixRotationZ(&matRotateZ,D3DXToRadian(rotation.z));
D3DXMatrixTranslation(&matTranslate, position.x, position.y, position.z);

matWorld = matRotateX * matRotateY * matRotateZ * matScale * matTranslate;


s.SetMatrix("World", matWorld);
s.SetMatrix("View", mView);
s.SetMatrix("Projection", mProjection);
}

void Model::Render(Shader s)
{

for (DWORD i=0; i<numMaterials; i++)
{

s.SetTexture("ModelTexture", meshTextures);

s.Begin();
mesh->DrawSubset( i );
s.End();
}
}


And this is from the Game clas I suspect the problem is in here with putting the models in a std::list

void Game::LoadObjects()
{
Model floors;
floors.SetDevice(device);
floors.Initialize();
floors.SetPosition(0,-10,0);
floors.SetScale(5,5,5);
floors.LoadContent("Content//Models//floor.x");

Model walls;
walls.SetDevice(device);
walls.Initialize();
walls.SetPosition(0,-10,0);
walls.SetScale(5,5,5);
walls.LoadContent("Content//Models//walls.x");



modelList.push_back(floors);
modelList.push_back(walls);


}


void Game::Update(float dt)
{

list<Model>::const_iterator it;
for(it=modelList.begin(); it!=modelList.end(); ++it)
{
it._Mynode()->_Myval.Update(camera.matView, camera.matProjection, ModelEffect);
}

}

void Game::Draw(float dt)
{
list<Model>::const_iterator it;
for(it=modelList.begin(); it!=modelList.end(); ++it)
{
it._Mynode()->_Myval.Render(ModelEffect);
}
}


Does anything look wrong there? If not I'll edit it and post the entire classes. Thanks so much.
As far as I can see, you are setting the shading parameters for all the models one after another without rendering anything, effectively overwriting the previous parameters. Than you start rendering, but of course now the parameters for the last model are set. Do the SetMatrix() stuff just before you render the model.

This topic is closed to new replies.

Advertisement