www.pudn.com > zfxcengine-0.1.0.zip > ceRenderQueue_D3D9.cpp
#include "Core/ceExceptions.h"
#include "Render/RenderD3D9/ceRenderQueue_D3D9.h"
#include "Render/RenderD3D9/ceRenderObject_D3D9.h"
#include "Core/ceMemManager.h"
namespace ZFXCE {
namespace Render {
//////////////////////////////////////////////////////////////////////////////
ceRenderQueueD3D9::ceRenderQueueD3D9(void):m_pD3DDevice(NULL),m_pRenderObjectFactory(NULL),m_CurrentFVF(0),
m_pTextureManager(NULL),m_iCurrentVB(-1),m_iCurrentIB(-1)
{
for(INT t=0; t < CE_RS_TEXUNITMAX; t++)
m_CurrentTextures[t] = -1;
ZeroMemory(&m_CurrentViewport, sizeof(m_CurrentViewport));
}
//////////////////////////////////////////////////////////////////////////////
ceRenderQueueD3D9::ceRenderQueueD3D9(LPDIRECT3DDEVICE9 D3DDevice, ceRenderObjectFactoryD3D9* ROF, ceTextureManagerD3D9* TM):
m_pD3DDevice(D3DDevice), m_pRenderObjectFactory(ROF),m_CurrentFVF(0),
m_pTextureManager(TM),m_iCurrentVB(-1),m_iCurrentIB(-1)
{
for(INT t=0; t < CE_RS_TEXUNITMAX; t++)
m_CurrentTextures[t] = -1;
ZeroMemory(&m_CurrentViewport, sizeof(m_CurrentViewport));
}
//////////////////////////////////////////////////////////////////////////////
ceRenderQueueD3D9::~ceRenderQueueD3D9(void)
{
m_RenderJobs.clear();
m_pRenderObjectFactory = NULL;
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::AddRenderJob(ceRenderJob* Job)
{
PUSH_FUNCTION;
m_RenderJobs.push_back( (ceRenderJobD3D9*) Job);
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::AddRenderJobs(ceRenderJob** Jobs, UINT Num)
{
PUSH_FUNCTION;
for(UINT j=0; j < Num; j++)
m_RenderJobs.push_back( (ceRenderJobD3D9*) Jobs[j] );
}
////////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::SetMisc(ceRenderJobD3D9* pRenderJob)
{
// Viewport des Jobs setzen
if ( m_CurrentViewport.m_uiX != pRenderJob->m_d3dViewport.X ||
m_CurrentViewport.m_uiY != pRenderJob->m_d3dViewport.Y ||
m_CurrentViewport.m_uiWidth != pRenderJob->m_d3dViewport.Width ||
m_CurrentViewport.m_uiHeight != pRenderJob->m_d3dViewport.Height )
{
// Jetzt den neuen setzen
m_pD3DDevice->SetViewport(&pRenderJob->m_d3dViewport);
// Neuer ist nu aktiv
m_CurrentViewport.m_uiX = pRenderJob->m_d3dViewport.X;
m_CurrentViewport.m_uiY = pRenderJob->m_d3dViewport.Y;
m_CurrentViewport.m_uiWidth = pRenderJob->m_d3dViewport.Width;
m_CurrentViewport.m_uiHeight = pRenderJob->m_d3dViewport.Height;
}
// World-Matrix (Model-Matrix) ändern.
m_pD3DDevice->SetTransform(D3DTS_WORLD, &pRenderJob->m_matWorld);
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::SetPass(ceRenderJobD3D9::SRenderPass *pPass)
{
PUSH_FUNCTION;
// Texturen
for(UINT t=0; t < CE_RS_TEXUNITMAX; t++)
{
if(pPass->TextureIDs[t] < 0)
{
m_pD3DDevice->SetTextureStageState(t, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pD3DDevice->SetTexture(t, NULL);
break;
}
else
{
if(m_CurrentTextures[t] != pPass->TextureIDs[t])
{
ceTextureObjectD3D9* tex = m_pTextureManager->GetObjectByID(pPass->TextureIDs[t]);
// Texturestates aktivieren
// Filter
if (CE_RS_TEXFILTER_LINEAR == pPass->TextureFilters[t])
{
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
}
else
{
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC );
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC );
switch (pPass->TextureFilters[t])
{
case CE_RS_TEXFILTER_ANISOTROPIC_2:
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAXANISOTROPY, 2 );
break;
case CE_RS_TEXFILTER_ANISOTROPIC_4:
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAXANISOTROPY, 4 );
break;
case CE_RS_TEXFILTER_ANISOTROPIC_8:
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAXANISOTROPY, 8 );
break;
case CE_RS_TEXFILTER_ANISOTROPIC_16:
m_pD3DDevice->SetSamplerState( t, D3DSAMP_MAXANISOTROPY, 16 );
break;
}
}
if (D3DTOP_DISABLE != pPass->TextureCombineMethod[t][0])
{
m_pD3DDevice->SetTextureStageState( t, D3DTSS_COLOROP, pPass->TextureCombineMethod[t][0]);
m_pD3DDevice->SetTextureStageState( t, D3DTSS_COLORARG0, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_COLORARG0] );
m_pD3DDevice->SetTextureStageState( t, D3DTSS_COLORARG1, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_COLORARG1] );
m_pD3DDevice->SetTextureStageState( t, D3DTSS_COLORARG2, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_COLORARG2] );
}
// Set alpha operation
if(D3DTOP_DISABLE != pPass->TextureCombineMethod[t][1])
{
m_pD3DDevice->SetTextureStageState( t, D3DTSS_ALPHAOP, pPass->TextureCombineMethod[t][1]);
m_pD3DDevice->SetTextureStageState( t, D3DTSS_ALPHAARG0, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_ALPHAARG0] );
m_pD3DDevice->SetTextureStageState( t, D3DTSS_ALPHAARG1, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_ALPHAARG1] );
m_pD3DDevice->SetTextureStageState( t, D3DTSS_ALPHAARG2, pPass->TextureCombineSources[t][CE_RS_TEXCOMBINE_ALPHAARG2] );
}
// Scaling?
// if(pass->TextureScalingColor != 1.0f)
// glTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, pass->TextureScalingColor);
m_pD3DDevice->SetTextureStageState( t, D3DTSS_TEXCOORDINDEX, t );
m_pD3DDevice->SetTexture(t, tex->m_pTexture);
m_CurrentTextures[t] = pPass->TextureIDs[t];
}
}
}
// VERTEX PIPE STATE
if (pPass->CullMode != m_CurrentPass.CullMode)
{
m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, pPass->CullMode);
m_CurrentPass.CullMode = pPass->CullMode;
}
// FRAGMENT PIPE STATE
// Alpha-Mode
if(m_CurrentPass.bAlphablending != pPass->bAlphablending)
{
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, pPass->bAlphablending);
m_CurrentPass.bAlphablending = pPass->bAlphablending;
}
if (m_CurrentPass.bAlphablending)
{
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, pPass->SourceBlendMode);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, pPass->DestBlendMode);
m_CurrentPass.SourceBlendMode = pPass->SourceBlendMode;
m_CurrentPass.DestBlendMode = pPass->DestBlendMode;
}
// Alpha-Testing
if (m_CurrentPass.bAlphaTesting != pPass->bAlphaTesting)
{
m_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, pPass->bAlphaTesting);
m_CurrentPass.bAlphaTesting = pPass->bAlphaTesting;
}
if (m_CurrentPass.bAlphaTesting)
{
m_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, pPass->dwAlphaRefValue);
m_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, pPass->ATCompareFunction);
m_CurrentPass.dwAlphaRefValue = pPass->dwAlphaRefValue;
m_CurrentPass.ATCompareFunction = pPass->ATCompareFunction;
}
// Color-Buffer
if (m_CurrentPass.bColorWrites != pPass->bColorWrites)
{
if (!pPass->bColorWrites)
m_pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, FALSE);
else
m_pD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA |
D3DCOLORWRITEENABLE_BLUE |
D3DCOLORWRITEENABLE_GREEN |
D3DCOLORWRITEENABLE_RED);
m_CurrentPass.bColorWrites = pPass->bColorWrites;
}
// Fill-Mode
if (m_CurrentPass.FillMode != pPass->FillMode)
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, pPass->FillMode );
m_CurrentPass.FillMode = pPass->FillMode;
}
// Z-Buffer
if (m_CurrentPass.bDepthTest != pPass->bDepthTest)
{
if (pPass->bDepthTest)
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
else
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
m_CurrentPass.bDepthTest = pPass->bDepthTest;
}
if (m_CurrentPass.ZFunction != pPass->ZFunction)
{
m_pD3DDevice->SetRenderState( D3DRS_ZFUNC, pPass->ZFunction );
m_CurrentPass.ZFunction = pPass->ZFunction;
}
if (m_CurrentPass.bDepthWrites != pPass->bDepthWrites)
{
m_pD3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, pPass->bDepthWrites );
m_CurrentPass.bDepthWrites = pPass->bDepthWrites;
}
// Stencil-Buffer
if (m_CurrentPass.bStencilTest != pPass->bStencilTest)
{
m_pD3DDevice->SetRenderState( D3DRS_STENCILENABLE, pPass->bStencilTest );
m_CurrentPass.bStencilTest = pPass->bStencilTest;
}
if (m_CurrentPass.bTwoSidedStencil != pPass->bTwoSidedStencil)
{
m_pD3DDevice->SetRenderState( D3DRS_TWOSIDEDSTENCILMODE, pPass->bTwoSidedStencil );
m_CurrentPass.bTwoSidedStencil = pPass->bTwoSidedStencil;
}
if(m_CurrentPass.bStencilTest)
{
for(UINT i=0; i<2; i++)
{
m_CurrentPass.StencilFail[i] = pPass->StencilFail[i];
m_CurrentPass.StencilZPass[i] = pPass->StencilZPass[i];
m_CurrentPass.StencilZFail[i] = pPass->StencilZFail[i];
m_CurrentPass.dwStencilMask[i] = pPass->dwStencilMask[i];
m_CurrentPass.dwStencilRef[i] = pPass->dwStencilRef[i];
m_CurrentPass.dwStencilWriteMask[i] = pPass->dwStencilWriteMask[i];
m_CurrentPass.StencilCompareFunction[i] = pPass->StencilCompareFunction[i];
}
m_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, pPass->StencilCompareFunction[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILREF, pPass->dwStencilRef[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILMASK, pPass->dwStencilMask[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILWRITEMASK,pPass->dwStencilWriteMask[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILZFAIL, pPass->StencilZFail[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILFAIL, pPass->StencilFail[0] );
m_pD3DDevice->SetRenderState( D3DRS_STENCILPASS, pPass->StencilZPass[0] );
if(m_CurrentPass.bTwoSidedStencil)
{
m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILFUNC, pPass->StencilCompareFunction[1] );
m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILFAIL, pPass->StencilFail[1] );
m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILZFAIL, pPass->StencilZFail[1] );
// m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILREF, pPass->dwStencilRef[1] );
// m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILMASK, pPass->dwStencilMask[1] );
// m_pD3DDevice->SetRenderState( D3DRS_CCW_STENCILWRITEMASK, pPass->dwStencilWriteMask[1] );
}
}
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::RenderWithIndices(ceRenderJobD3D9 *pJob)
{
PUSH_FUNCTION;
unsigned int i=0;
ceVertexBufferD3D9* vb = (ceVertexBufferD3D9*) m_pRenderObjectFactory->GetRenderObject(pJob->m_VertexBuffer);
ceIndexBufferD3D9* ib = (ceIndexBufferD3D9*) m_pRenderObjectFactory->GetRenderObject(pJob->m_IndexBuffer);
// Indexbuffer aktivieren.
if (m_iCurrentIB != pJob->m_IndexBuffer)
{
m_pD3DDevice->SetIndices(ib->m_IndexBuffer);
m_iCurrentIB = pJob->m_IndexBuffer;
}
// FVF aktivieren
if(m_CurrentFVF != vb->m_D3DFVF)
{
// m_pD3DDevice->SetVertexDeclaration( NULL );
m_pD3DDevice->SetFVF(vb->m_D3DFVF);
m_CurrentFVF = vb->m_D3DFVF;
}
// Vertexbuffer aktivieren.
if (m_iCurrentVB != pJob->m_VertexBuffer)
{
m_pD3DDevice->SetStreamSource(0, vb->m_VertexBuffer, 0, vb->GetVertexSize() );
m_iCurrentVB = pJob->m_VertexBuffer;
}
SetMisc(pJob);
for (i=0; im_Passes.size(); i++)
{
SetPass(&pJob->m_Passes[i]);
m_pD3DDevice->DrawIndexedPrimitive(ib->m_D3DPrimType, 0, 0, vb->GetNumOfVertices(), 0, ib->m_NumOfPrimitives);
}
/* ceVertexBufferD3D9* vb = (ceVertexBufferD3D9*) m_pRenderObjectFactory->GetRenderObject(pJob->m_VertexBuffer);
// 2.) FVF aktivieren
if(m_CurrentFVF != vb->m_D3DFVF)
{
m_pD3DDevice->SetVertexDeclaration( NULL );
m_pD3DDevice->SetFVF(vb->m_D3DFVF);
m_CurrentFVF = vb->m_D3DFVF;
}
// 3.) Vertexbuffer aktivieren.
if(FAILED(m_pD3DDevice->SetStreamSource(0, vb->m_VertexBuffer, 0, vb->GetVertexSize() ) ))
CE_EXCEPTION("SetStreamSource", CELS_ERROR);
// 4.) Indexbuffer aktivieren und zeichnen
if(pJob->m_IndexBuffer == -1)
{
if(FAILED(m_pD3DDevice->DrawPrimitive(vb->m_D3DPrimType, 0, vb->m_NumOfPrimitives) ))
CE_EXCEPTION("DrawPrimitive", CELS_ERROR);
}
else
{
ceIndexBufferD3D9* ib = (ceIndexBufferD3D9*) m_pRenderObjectFactory->GetRenderObject(pJob->m_IndexBuffer);
m_pD3DDevice->SetIndices(ib->m_IndexBuffer);
m_pD3DDevice->DrawIndexedPrimitive(ib->m_D3DPrimType, 0, 0, vb->GetNumOfVertices(), 0, ib->m_NumOfPrimitives);
}*/
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::RenderWithoutIndices(ceRenderJobD3D9 *pJob)
{
PUSH_FUNCTION;
unsigned int i=0;
ceVertexBufferD3D9* vb = (ceVertexBufferD3D9*) m_pRenderObjectFactory->GetRenderObject(pJob->m_VertexBuffer);
// FVF aktivieren
if(m_CurrentFVF != vb->m_D3DFVF)
{
// m_pD3DDevice->SetVertexDeclaration( NULL );
m_pD3DDevice->SetFVF(vb->m_D3DFVF);
m_CurrentFVF = vb->m_D3DFVF;
}
// Vertexbuffer aktivieren.
if (m_iCurrentVB != pJob->m_VertexBuffer)
{
m_pD3DDevice->SetStreamSource(0, vb->m_VertexBuffer, 0, vb->GetVertexSize() );
m_iCurrentVB = pJob->m_VertexBuffer;
}
// Indexbuffer aktivieren.
if (-1 != m_iCurrentIB)
{
m_pD3DDevice->SetIndices(NULL);
m_iCurrentIB = -1;
}
SetMisc(pJob);
for (i=0; im_Passes.size(); i++)
{
SetPass(&pJob->m_Passes[i]);
m_pD3DDevice->DrawPrimitive(vb->m_D3DPrimType, 0, vb->m_NumOfPrimitives);
}
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::Render(ceRenderJobD3D9 *pJob)
{
PUSH_FUNCTION;
// Nur via Vertexbuffer rendern, wenn kein Indexbuffer gesetzt ist!
if(pJob->GetJobType() == CE_RENDEROBJECT_VERTEX_BUFFER)
{
RenderWithoutIndices(pJob);
return;
}
// Mit Indexbuffer rendern, falls gesetzt
else if(pJob->GetJobType() == CE_RENDEROBJECT_INDEX_BUFFER)
{
RenderWithIndices(pJob);
return;
}
// Nur Indexbuffern rendern gibts nicht
assert(false && "Unknown RenderJob Type!");
}
//////////////////////////////////////////////////////////////////////////////
void ceRenderQueueD3D9::RenderAll(void)
{
assert(m_pRenderObjectFactory != NULL);
assert(m_pD3DDevice != NULL);
RenderJobList::iterator JobIter;
for(JobIter=m_RenderJobs.begin(); JobIter != m_RenderJobs.end(); JobIter++)
Render(*JobIter);
m_RenderJobs.clear();
}
} // namespace Rende
} // namespace ZFXCE