/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Copyright (C) 2006-2010 - Frictional Games * * This file is part of HPL1 Engine. */ #include "hpl1/engine/graphics/RenderList.h" #include "hpl1/engine/graphics/Graphics.h" #include "hpl1/engine/graphics/Material.h" #include "hpl1/engine/graphics/RenderState.h" #include "hpl1/engine/graphics/Renderable.h" #include "hpl1/engine/graphics/Renderer3D.h" #include "hpl1/engine/graphics/RendererPostEffects.h" #include "hpl1/engine/math/Math.h" #include "hpl1/engine/scene/Camera3D.h" #include "hpl1/engine/scene/MeshEntity.h" namespace hpl { int cRenderList::mlGlobalRenderCount = 0; ////////////////////////////////////////////////////////////////////////// // MOTION BLUR OBJECT COMPARE ////////////////////////////////////////////////////////////////////////// bool cMotionBlurObject_Compare::operator()(iRenderable *pObjectA, iRenderable *pObjectB) const { // TODO: perhaps Z here... return pObjectA->GetVertexBuffer() < pObjectB->GetVertexBuffer(); } ////////////////////////////////////////////////////////////////////////// // TRANSPERANT OBJECT COMPARE ////////////////////////////////////////////////////////////////////////// bool cTransperantObject_Compare::operator()(iRenderable *pObjectA, iRenderable *pObjectB) const { if (pObjectA->GetMaterial()->GetDepthTest() != pObjectA->GetMaterial()->GetDepthTest()) { return pObjectA->GetMaterial()->GetDepthTest() < pObjectA->GetMaterial()->GetDepthTest(); } return pObjectA->GetZ() < pObjectB->GetZ(); } ////////////////////////////////////////////////////////////////////////// // QUERY COMPARE ////////////////////////////////////////////////////////////////////////// bool cOcclusionQueryObject_Compare::operator()(const cOcclusionQueryObject *pObjectA, const cOcclusionQueryObject *pObjectB) const { if (pObjectA->mpVtxBuffer != pObjectB->mpVtxBuffer) return pObjectA->mpVtxBuffer < pObjectB->mpVtxBuffer; if (pObjectA->mpMatrix != pObjectB->mpMatrix) return pObjectA->mpMatrix < pObjectB->mpMatrix; return (int)pObjectA->mbDepthTest < (int)pObjectB->mbDepthTest; } ////////////////////////////////////////////////////////////////////////// // RENDER NODE ////////////////////////////////////////////////////////////////////////// cMemoryPool *g_poolRenderState = NULL; cMemoryPool *g_poolRenderNode = NULL; //----------------------------------------------------------------------- bool cRenderNodeCompare::operator()(cRenderNode *apNodeA, cRenderNode *apNodeB) const { int val = apNodeA->mpState->Compare(apNodeB->mpState); bool ret = val > 0 ? true : false; return ret; } //----------------------------------------------------------------------- void cRenderNode::DeleteChildren() { tRenderNodeSetIt it = m_setNodes.begin(); for (; it != m_setNodes.end(); ++it) { cRenderNode *pNode = *it; pNode->DeleteChildren(); g_poolRenderNode->Release(pNode); } if (mpState) g_poolRenderState->Release(mpState); mpState = NULL; m_setNodes.clear(); } //----------------------------------------------------------------------- void cRenderNode::Render(cRenderSettings *apSettings) { tRenderNodeSetIt it = m_setNodes.begin(); for (; it != m_setNodes.end(); ++it) { cRenderNode *pNode = *it; pNode->mpState->SetMode(apSettings); pNode->Render(apSettings); } } ////////////////////////////////////////////////////////////////////////// // CONSTRUCTORS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cRenderList::cRenderList(cGraphics *apGraphics) { mfFrameTime = 0; mTempNode.mpState = hplNew(iRenderState, ()); mlRenderCount = 0; mlLastRenderCount = 0; mpGraphics = apGraphics; m_poolRenderState = hplNew(cMemoryPool, (3000, NULL)); m_poolRenderNode = hplNew(cMemoryPool, (3000, NULL)); g_poolRenderState = m_poolRenderState; g_poolRenderNode = m_poolRenderNode; } //----------------------------------------------------------------------- cRenderList::~cRenderList() { Clear(); hplDelete(mTempNode.mpState); hplDelete(m_poolRenderState); hplDelete(m_poolRenderNode); g_poolRenderState = NULL; g_poolRenderNode = NULL; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- void cRenderList::Clear() { ++mlGlobalRenderCount; // Clear containers. m_setLights.clear(); m_setObjects.clear(); m_setQueries.clear(); m_setMotionBlurObjects.clear(); m_setTransperantObjects.clear(); mRootNodeDepth.DeleteChildren(); mRootNodeDiffuse.DeleteChildren(); mRootNodeTrans.DeleteChildren(); for (int i = 0; i < MAX_NUM_OF_LIGHTS; i++) { mRootNodeLight[i].DeleteChildren(); } mlLastRenderCount = mlRenderCount; mlRenderCount++; } //----------------------------------------------------------------------- void cRenderList::AddOcclusionQuery(cOcclusionQueryObject *apObject) { m_setQueries.insert(apObject); } //----------------------------------------------------------------------- cOcclusionQueryObjectIterator cRenderList::GetQueryIterator() { return cOcclusionQueryObjectIterator(&m_setQueries); } //----------------------------------------------------------------------- cMotionBlurObjectIterator cRenderList::GetMotionBlurIterator() { return cMotionBlurObjectIterator(&m_setMotionBlurObjects); } //----------------------------------------------------------------------- cTransperantObjectIterator cRenderList::GetTransperantIterator() { return cTransperantObjectIterator(&m_setTransperantObjects); } //----------------------------------------------------------------------- cLight3DIterator cRenderList::GetLightIt() { return cLight3DIterator(&m_setLights); } //----------------------------------------------------------------------- cRenderableIterator cRenderList::GetObjectIt() { return cRenderableIterator(&m_setObjects); } //----------------------------------------------------------------------- int cRenderList::GetLightNum() { return (int)m_setLights.size(); } int cRenderList::GetObjectNum() { return (int)m_setObjects.size(); } //----------------------------------------------------------------------- cRenderNode *cRenderList::GetRootNode(eRenderListDrawType aObjectType, eMaterialRenderType aPassType, int alLightNum) { if (aObjectType == eRenderListDrawType_Normal) { if (aPassType == eMaterialRenderType_Z) return &mRootNodeDepth; if (aPassType == eMaterialRenderType_Diffuse) return &mRootNodeDiffuse; if (aPassType == eMaterialRenderType_Light) return &mRootNodeLight[alLightNum]; return NULL; } else { return &mRootNodeTrans; } } //----------------------------------------------------------------------- void cRenderList::Compile() { int lLightNum = (int)m_setLights.size(); if (lLightNum > MAX_NUM_OF_LIGHTS) lLightNum = MAX_NUM_OF_LIGHTS; for (int i = 0; i < lLightNum; ++i) mvObjectsPerLight[i] = 0; // Iterate the objects to be rendered and build trees with render states. tRenderableSetIt it = m_setObjects.begin(); for (; it != m_setObjects.end(); ++it) { iRenderable *pObject = *it; iMaterial *pMat = pObject->GetMaterial(); // Skip meshes... if (pObject->GetRenderType() == eRenderableType_Mesh) continue; // If the object is transparent add tot eh trans tree if (pMat->IsTransperant()) { // Use the set cotainer instead for now: m_setTransperantObjects.insert(pObject); /*for(int lPass=0; lPass< pMat->GetNumOfPasses(eMaterialRenderType_Diffuse, NULL);lPass++) { AddToTree(pObject,eRenderListDrawType_Trans, eMaterialRenderType_Light,0,NULL, true,lPass); }*/ } // If object is not trans add to another tree. else { // If the object uses z pass add to z tree. if (pMat->UsesType(eMaterialRenderType_Z)) { for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Z, NULL); lPass++) { AddToTree(pObject, eRenderListDrawType_Normal, eMaterialRenderType_Z, 0, NULL, false, lPass); } } // If object uses light add the object to each light's tree. if (pMat->UsesType(eMaterialRenderType_Light)) { // Light trees that the object will belong to. int lLightCount = 0; tLight3DSetIt lightIt = m_setLights.begin(); for (; lightIt != m_setLights.end(); ++lightIt) { iLight3D *pLight = *lightIt; if ((pLight->GetOnlyAffectInSector() == false || pObject->IsInSector(pLight->GetCurrentSector())) && pLight->CheckObjectIntersection(pObject)) { if (lLightCount >= MAX_NUM_OF_LIGHTS) break; ++mvObjectsPerLight[lLightCount]; for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Light, pLight); ++lPass) { AddToTree(pObject, eRenderListDrawType_Normal, eMaterialRenderType_Light, lLightCount, pLight, false, lPass); } } ++lLightCount; } } // If it has a diffuse pass, add to the diffuse tree. if (pObject->GetMaterial()->UsesType(eMaterialRenderType_Diffuse)) { for (int lPass = 0; lPass < pMat->GetNumOfPasses(eMaterialRenderType_Diffuse, NULL); lPass++) { AddToTree(pObject, eRenderListDrawType_Normal, eMaterialRenderType_Diffuse, 0, NULL, false, lPass); } } } } } //----------------------------------------------------------------------- bool cRenderList::Add(iRenderable *apObject) { if (apObject->IsVisible() == false) return false; // Check if the object is culled by fog. cRenderer3D *pRenderer = mpGraphics->GetRenderer3D(); if (pRenderer->GetFogActive() && pRenderer->GetFogCulling()) { if (cMath::CheckCollisionBV(*pRenderer->GetFogBV(), *apObject->GetBoundingVolume())) { } else { return false; } } // Check if the object as already been added. if (mlRenderCount == apObject->GetRenderCount()) return false; apObject->SetRenderCount(mlRenderCount); // Update the graphics of object. apObject->UpdateGraphics(cRenderList::GetCamera(), mfFrameTime, this); // Set that the object is to be rendered. apObject->SetGlobalRenderCount(mlGlobalRenderCount); switch (apObject->GetRenderType()) { // Add a normal renderable case eRenderableType_Normal: case eRenderableType_ParticleSystem: if (apObject->GetMaterial()->IsTransperant()) { // Calculate the Z for the trans object cVector3f vCameraPos = cMath::MatrixMul(cRenderList::GetCamera()->GetViewMatrix(), apObject->GetBoundingVolume()->GetWorldCenter()); apObject->SetZ(vCameraPos.z); m_setObjects.insert(apObject); } else { m_setObjects.insert(apObject); // MotionBlur if (mpGraphics->GetRendererPostEffects()->GetMotionBlurActive() || mpGraphics->GetRenderer3D()->GetRenderSettings()->mbFogActive || mpGraphics->GetRendererPostEffects()->GetDepthOfFieldActive()) { m_setMotionBlurObjects.insert(apObject); if (apObject->GetPrevRenderCount() != GetLastRenderCount()) { cMatrixf *pMtx = apObject->GetModelMatrix(mpCamera); if (pMtx) { apObject->SetPrevMatrix(*pMtx); } } apObject->SetPrevRenderCount(mlRenderCount); } } break; // Add all sub meshes of the mesh case eRenderableType_Mesh: { cMeshEntity *pMesh = static_cast(apObject); for (int i = 0; i < pMesh->GetSubMeshEntityNum(); i++) { Add(pMesh->GetSubMeshEntity(i)); } break; } // Add a light to a special container case eRenderableType_Light: { iLight3D *pLight = static_cast(apObject); m_setLights.insert(pLight); } break; default: break; } return true; } //----------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////// // PRIVATE METHODS ////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------- cRenderNode *cRenderList::InsertNode(cRenderNode *apListNode, cRenderNode *apTempNode) { // Log("Searching for node... "); // Create a node with the state. tRenderNodeSetIt it = apListNode->m_setNodes.find(apTempNode); if (it != apListNode->m_setNodes.end()) { // Log("Node found!\n"); // node found, return it. return *it; } else { // Log("Node NOT found, creating new.\n"); // no node found, create one and return it. cRenderNode *pNode = m_poolRenderNode->Create(); pNode->mpState = m_poolRenderState->Create(); // Copy the relevant values to the state. pNode->mpState->Set(apTempNode->mpState); apListNode->m_setNodes.insert(pNode); return pNode; } } //----------------------------------------------------------------------- /*cRenderNode* cRenderList::InsertNode(cRenderNode* apListNode, cRenderNode* apTempNode) { Std::pair ret = apListNode->m_setNodes.insert(apTempNode); if(ret.second == false) { m_poolRenderState->Release(apTempNode->mpState); m_poolRenderNode->Release(apTempNode); return *ret.first; } return apTempNode; }*/ //----------------------------------------------------------------------- void cRenderList::AddToTree(iRenderable *apObject, eRenderListDrawType aObjectType, eMaterialRenderType aPassType, int alLightNum, iLight3D *apLight, bool abUseDepth, int alPass) { // Log("------ OBJECT ------------\n"); cRenderNode *pNode = GetRootNode(aObjectType, aPassType, alLightNum); iMaterial *pMaterial = apObject->GetMaterial(); iRenderState *pTempState = mTempNode.mpState; cRenderNode *pTempNode = &mTempNode; //-------------- EXPLANATION ---------------------------------- // Go through each render state type and set the appropriate // variables for each type. The most important states are set first. // The state is then inserted to a tree structure, where each state type is a level. // Example: // |----------root--------| // |---pass |-----pass----| // depth-test depth-test depth-test // ............etc...................... // After each insertion a pointer to the inserted or existing (if variables already existed) // node is returned // This is then passed on the next state, the state inserted (or exist found) there and so on. // At each insertion, it is first checked if a state with variables exist, and if so, use that. // if not, a new node is created and inserted. // The temp node state is used as storage for the data to skip the overhead of deletion // and creation when testing if state exist. Instead new data is only created if the state // is new. // Each Render state has the same class, but uses different var depending on type, this to // skip the overhead of using inheritance. //------------------------------------------------------------- /////// SECTOR ////////////// if (aPassType == eMaterialRenderType_Z) { // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Sector; pTempState->mpSector = apObject->GetCurrentSector(); pNode = InsertNode(pNode, pTempNode); } /////// PASS ////////////// { // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Pass; pTempState->mlPass = alPass; pNode = InsertNode(pNode, pTempNode); } /////// DEPTH TEST ////////////// { // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; // Log("\nDepth level, Z: %f\n",apObject->GetZ()); pTempState->mType = eRenderStateType_DepthTest; pTempState->mbDepthTest = pMaterial->GetDepthTest(); pNode = InsertNode(pNode, pTempNode); } /////// DEPTH ////////////// if (abUseDepth) { // Log("\nDepth level, Z: %f\n",apObject->GetZ()); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Depth; pTempState->mfZ = apObject->GetZ(); pNode = InsertNode(pNode, pTempNode); } /////// ALPHA MODE ////////////// { // Log("\nAlpha level %d\n", pMaterial->GetAlphaMode(mType,alPass)); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_AlphaMode; pTempState->mAlphaMode = pMaterial->GetAlphaMode(aPassType, alPass, apLight); pNode = InsertNode(pNode, pTempNode); } /////// BLEND MODE ////////////// { // Log("\nBlend level %d : %d\n",pMaterial->GetBlendMode(mType,alPass),pMaterial->GetChannelMode(mType,alPass)); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_BlendMode; pTempState->mBlendMode = pMaterial->GetBlendMode(aPassType, alPass, apLight); pTempState->mChannelMode = pMaterial->GetChannelMode(aPassType, alPass, apLight); pNode = InsertNode(pNode, pTempNode); } /////// GPU PROGRAM ////////////// { pTempState->mType = eRenderStateType_GpuProgram; pTempState->gpuProgram = pMaterial->getGpuProgram(aPassType, alPass, apLight); pTempState->gpuProgramSetup = pMaterial->getGpuProgramSetup(aPassType, alPass, apLight); pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass, apLight); pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass, apLight); pTempState->mpLight = apLight; pNode = InsertNode(pNode, pTempNode); } #if 0 /////// VERTEX PROGRAM ////////////// { // Log("\nVertex program level\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_VertexProgram; pTempState->mpVtxProgram = pMaterial->GetVertexProgram(aPassType, alPass, apLight); pTempState->mpVtxProgramSetup = pMaterial->GetVertexProgramSetup(aPassType, alPass, apLight); pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass, apLight); pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass, apLight); pTempState->mpLight = apLight; pNode = InsertNode(pNode, pTempNode); } /////// FRAGMENT PROGRAM ////////////// { // Log("\nFragment program level\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_FragmentProgram; pTempState->mpFragProgram = pMaterial->GetFragmentProgram(aPassType, alPass, apLight); pTempState->mpFragProgramSetup = pMaterial->GetFragmentProgramSetup(aPassType, alPass, apLight); pNode = InsertNode(pNode, pTempNode); } #endif /////// TEXTURE ////////////// { // Log("\nTexture level\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Texture; for (int i = 0; i < MAX_TEXTUREUNITS; i++) { pTempState->mpTexture[i] = pMaterial->GetTexture(i, aPassType, alPass, apLight); } pNode = InsertNode(pNode, pTempNode); } /////// VERTEX BUFFER ////////////// { // Log("\nVertex buffer level\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_VertexBuffer; pTempState->mpVtxBuffer = apObject->GetVertexBuffer(); pNode = InsertNode(pNode, pTempNode); } /////// MATRIX ////////////// { // Log("\nMatrix level\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Matrix; pTempState->mpModelMatrix = apObject->GetModelMatrix(mpCamera); pTempState->mpInvModelMatrix = apObject->GetInvModelMatrix(); pTempState->mvScale = apObject->GetCalcScale(); pNode = InsertNode(pNode, pTempNode); } /////// RENDER ////////////// { // Log("\nRender leaf!\n"); // pTempNode = m_poolRenderNode->Create(); // pTempState = m_poolRenderState->Create(); // pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Render; pTempState->mpObject = apObject; InsertNode(pNode, pTempNode); } // Log("-------------------------\n"); } //---------------------------------------------------------------------------------------------- /*void cRenderList::AddToTree(iRenderable* apObject,eRenderListDrawType aObjectType, eMaterialRenderType aPassType, int alLightNum,iLight3D* apLight, bool abUseDepth, int alPass) { //Log("------ OBJECT ------------\n"); cRenderNode *pNode = GetRootNode(aObjectType,aPassType, alLightNum); iMaterial *pMaterial = apObject->GetMaterial(); iRenderState *pTempState = NULL;//mTempNode.mpState; cRenderNode *pTempNode = NULL; //-------------- EXPLANATION ---------------------------------- // Go through each render state type and set the appropriate // variables for each type. The most important states are set first. // The state is then inserted to a tree structure, where each state type is a level. // Example: // |----------root--------| // |---pass |-----pass----| // depth-test depth-test depth-test // ............etc...................... // After each insertion a pointer to the inserted or existing (if variables already existed) // node is returned // This is then passed on the next state, the state inserted (or exist found) there and so on. // At each insertion, it is first checked if a state with variables exist, and if so, use that. // if not, a new node is created and inserted. // The temp node state is used as storage for the data to skip the overhead of deletion // and creation when testing if state exist. Instead new data is only created if the state // is new. // Each Render state has the same class, but uses different var depending on type, this to // skip the overhead of using inheritance. //------------------------------------------------------------- /////// SECTOR ////////////// if(aPassType == eMaterialRenderType_Z) { pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Sector; pTempState->mpSector = apObject->GetCurrentSector(); pNode = InsertNode(pNode, pTempNode); } /////// PASS ////////////// { pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Pass; pTempState->mlPass = alPass; pNode = InsertNode(pNode, pTempNode); } /////// DEPTH TEST ////////////// { pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; //Log("\nDepth level, Z: %f\n",apObject->GetZ()); pTempState->mType = eRenderStateType_DepthTest; pTempState->mbDepthTest = pMaterial->GetDepthTest(); pNode = InsertNode(pNode, pTempNode); } /////// DEPTH ////////////// if(abUseDepth) { //Log("\nDepth level, Z: %f\n",apObject->GetZ()); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Depth; pTempState->mfZ = apObject->GetZ(); pNode = InsertNode(pNode, pTempNode); } /////// ALPHA MODE ////////////// { //Log("\nAlpha level %d\n", pMaterial->GetAlphaMode(mType,alPass)); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_AlphaMode; pTempState->mAlphaMode = pMaterial->GetAlphaMode(aPassType,alPass, apLight); pNode = InsertNode(pNode, pTempNode); } /////// BLEND MODE ////////////// { //Log("\nBlend level %d : %d\n",pMaterial->GetBlendMode(mType,alPass),pMaterial->GetChannelMode(mType,alPass)); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_BlendMode; pTempState->mBlendMode = pMaterial->GetBlendMode(aPassType,alPass,apLight); pTempState->mChannelMode = pMaterial->GetChannelMode(aPassType,alPass,apLight); pNode = InsertNode(pNode, pTempNode); } /////// VERTEX PROGRAM ////////////// { //Log("\nVertex program level\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_VertexProgram; pTempState->mpVtxProgram = pMaterial->GetVertexProgram(aPassType,alPass,apLight); pTempState->mpVtxProgramSetup = pMaterial->GetVertexProgramSetup(aPassType,alPass,apLight); pTempState->mbUsesLight = pMaterial->VertexProgramUsesLight(aPassType, alPass,apLight); pTempState->mbUsesEye = pMaterial->VertexProgramUsesEye(aPassType, alPass,apLight); pTempState->mpLight = apLight; pNode = InsertNode(pNode, pTempNode); } /////// FRAGMENT PROGRAM ////////////// { //Log("\nFragment program level\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_FragmentProgram; pTempState->mpFragProgram = pMaterial->GetFragmentProgram(aPassType,alPass,apLight); pNode = InsertNode(pNode, pTempNode); } /////// TEXTURE ////////////// { //Log("\nTexture level\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Texture; for(int i=0; impTexture[i] = pMaterial->GetTexture(i,aPassType, alPass,apLight); } pNode = InsertNode(pNode, pTempNode); } /////// VERTEX BUFFER ////////////// { //Log("\nVertex buffer level\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_VertexBuffer; pTempState->mpVtxBuffer = apObject->GetVertexBuffer(); pNode = InsertNode(pNode, pTempNode); } /////// MATRIX ////////////// { //Log("\nMatrix level\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Matrix; pTempState->mpModelMatrix = apObject->GetModelMatrix(mpCamera); pTempState->mpInvModelMatrix = apObject->GetInvModelMatrix(); pTempState->mvScale = apObject->GetCalcScale(); pNode = InsertNode(pNode, pTempNode); } /////// RENDER ////////////// { //Log("\nRender leaf!\n"); pTempNode = m_poolRenderNode->Create(); pTempState = m_poolRenderState->Create(); pTempNode->mpState = pTempState; pTempState->mType = eRenderStateType_Render; pTempState->mpObject = apObject; InsertNode(pNode, pTempNode); } //Log("-------------------------\n"); }*/ //----------------------------------------------------------------------- } // namespace hpl