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