In my implementation the models don't have access to the render queue, (in my opinion the model class should be independent on the Renderer), instead the model class has a method getStateGroups() an array containing the effect, material, mesh, model state groups.
My implementation isn't that different. I just gave the model a "Render"-method where I pass the render queue and let it submit its sort key, state groups and draw command.
void Model::Draw(render::IRenderer& render) const
{
const render::StateGroup* pInstanceStates = &m_states;
const render::StateGroup* pMaterialStates = &m_pMaterial->GetState();
const render::StateGroup* pEffectStates = &m_pMaterial->GetEffect().GetState();
const render::StateGroup* pMeshStates = &m_pMesh->GetState();
const render::StateGroup* groupArr[4] = { pInstanceStates, pMaterialStates, pEffectStates, pMeshStates };
render.Render(m_sortKey, &m_pMesh->GetDraw(), groupArr, 4);
}
I do agree that the model probably should be completely independand of the renderer, but for now, it works OK (going to change that somewhen). Note that I've adapted Hodgmans method of having draw calls seperated from state groups, and create an "render instance" out of all this data...
The Stage group is submitted individually before the models. How do you bind render targets/depth stencil buffers?
Right now the bound render targets are determined by the effect only:
void Effect::RenderTarget(unsigned int index, const Texture* pTexture)
{
const D3DTexture* pD3DTexture = nullptr;
if(pTexture != nullptr)
pD3DTexture = &pTexture->GetD3DTexture();
switch(index)
{
case 0:
m_states.Add<render::BindRenderTarget0>(*pD3DTexture);
break;
case 1:
m_states.Add<render::BindRenderTarget1>(*pD3DTexture);
break;
case 2:
m_states.Add<render::BindRenderTarget2>(*pD3DTexture);
break;
case 3:
m_states.Add<render::BindRenderTarget2>(*pD3DTexture);
break;
}
}
I don't really know what else I'm going to need (probably per-material/per-instance/per-pass render targets too?), but as far as this is concerned, would you say this is ok? As far as clearing render targets goes, it obviously can't be per-effect, since that would clear the target every time I e.g. render another one of my lights, etc...
I don't have commands to set individual constants, instead I work with constant buffers, the model "SetVertexConstant"-method will change the value of the constant in a POD buffer then the model uses two commands, UpdateCBuffer (that fills a D3D buffer with the contents of the POD buffer containing the constants) and VSBindCBuffer0 (that binds the D3D buffer to the constant buffer slot 0 of the vertex stage)
I quess you are working with DirectX 11? does this concept of constant buffers also translate to DirectX9? In DX9 I've got up to 256 (I quess) constant registeres, and I figured the best direct way for now was to simply adress the register directly (when I'm going to implement shader permutations etc.. I'm going to think about another solution anyway)...
But as for the render target clearing, where'd you say this would fit here?