void AtlasClipMapBatcher::renderClipMap( SceneGraphData& sgData, BaseMatInstance* overrideMat ) { PROFILE_START(AtlasClipMapBatcher_renderClipMap); for(S32 curBin=1; curBin<4; curBin++) { // If bin is empty, skip. if(mRenderList[curBin].size() == 0) continue; for(S32 i=0; i<mRenderList[curBin].size(); i++) { // Grab the render note. const RenderNote *rn = mRenderList[curBin][i]; // Set up clipmap levels. if( !mFixedFunction ) { BaseMatInstance* material = overrideMat; if( !material ) switch( rn->levelCount ) { case 2: material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart, -1, -1, false ); break; case 3: material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 1, rn->levelStart, -1, false ); break; case 4: material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 2, rn->levelStart + 1, rn->levelStart, false ); break; default: material = MaterialManager::get()->getWarningMatInstance(); } while( material->setupPass( mState, sgData ) ) rn->chunk->render(); } else { Point4F clipmapMapping; for( U32 curLayer = rn->levelEnd; curLayer >= rn->levelStart; -- curLayer ) { BaseMatInstance* material = overrideMat; if( !material ) material = mClipMap->bindTexturesFF( curLayer, clipmapMapping, curLayer == rn->levelEnd, false ); while( material->setupPass( mState, sgData ) ) rn->chunk->render(); } } } } PROFILE_END(); }
//----------------------------------------------------------------------------- // render //----------------------------------------------------------------------------- void RenderMeshMgr::render(SceneRenderState * state) { PROFILE_SCOPE(RenderMeshMgr_render); // Early out if nothing to draw. if(!mElementList.size()) return; GFXDEBUGEVENT_SCOPE( RenderMeshMgr_Render, ColorI::GREEN ); // Automagically save & restore our viewport and transforms. GFXTransformSaver saver; // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); matrixSet.restoreSceneViewProjection(); // init loop data GFXTextureObject *lastLM = NULL; GFXCubemap *lastCubemap = NULL; GFXTextureObject *lastReflectTex = NULL; GFXTextureObject *lastMiscTex = NULL; SceneData sgData; sgData.init( state ); U32 binSize = mElementList.size(); for( U32 j=0; j<binSize; ) { MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst); setupSGData( ri, sgData ); BaseMatInstance *mat = ri->matInst; // If we have an override delegate then give it a // chance to swap the material with another. if ( mMatOverrideDelegate ) { mat = mMatOverrideDelegate( mat ); if ( !mat ) { j++; continue; } } if( !mat ) mat = MATMGR->getWarningMatInstance(); U32 matListEnd = j; lastMiscTex = sgData.miscTex; U32 a; while( mat && mat->setupPass(state, sgData ) ) { for( a=j; a<binSize; a++ ) { MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst); // Check to see if we need to break this batch. if ( newPassNeeded( ri, passRI ) || lastMiscTex != passRI->miscTex ) { lastLM = NULL; break; } matrixSet.setWorld(*passRI->objectToWorld); matrixSet.setView(*passRI->worldToCamera); matrixSet.setProjection(*passRI->projection); mat->setTransforms(matrixSet, state); setupSGData( passRI, sgData ); mat->setSceneInfo( state, sgData ); // If we're instanced then don't render yet. if ( mat->isInstanced() ) { // Let the material increment the instance buffer, but // break the batch if it runs out of room for more. if ( !mat->stepInstance() ) { a++; break; } continue; } // TODO: This could proably be done in a cleaner way. // // This section of code is dangerous, it overwrites the // lightmap values in sgData. This could be a problem when multiple // render instances use the same multi-pass material. When // the first pass is done, setupPass() is called again on // the material, but the lightmap data has been changed in // sgData to the lightmaps in the last renderInstance rendered. // This section sets the lightmap data for the current batch. // For the first iteration, it sets the same lightmap data, // however the redundancy will be caught by GFXDevice and not // actually sent to the card. This is done for simplicity given // the possible condition mentioned above. Better to set always // than to get bogged down into special case detection. //------------------------------------- bool dirty = false; // set the lightmaps if different if( passRI->lightmap && passRI->lightmap != lastLM ) { sgData.lightmap = passRI->lightmap; lastLM = passRI->lightmap; dirty = true; } // set the cubemap if different. if ( passRI->cubemap != lastCubemap ) { sgData.cubemap = passRI->cubemap; lastCubemap = passRI->cubemap; dirty = true; } if ( passRI->reflectTex != lastReflectTex ) { sgData.reflectTex = passRI->reflectTex; lastReflectTex = passRI->reflectTex; dirty = true; } if ( dirty ) mat->setTextureStages( state, sgData ); // Setup the vertex and index buffers. mat->setBuffers( passRI->vertBuff, passRI->primBuff ); // Render this sucker. if ( passRI->prim ) GFX->drawPrimitive( *passRI->prim ); else GFX->drawPrimitive( passRI->primBuffIndex ); } // Draw the instanced batch. if ( mat->isInstanced() ) { // Sets the buffers including the instancing stream. mat->setBuffers( ri->vertBuff, ri->primBuff ); // Render the instanced stream. if ( ri->prim ) GFX->drawPrimitive( *ri->prim ); else GFX->drawPrimitive( ri->primBuffIndex ); } matListEnd = a; } // force increment if none happened, otherwise go to end of batch j = ( j == matListEnd ) ? j+1 : matListEnd; } }
void RenderGlowMgr::render( SceneRenderState *state ) { PROFILE_SCOPE( RenderGlowMgr_Render ); if ( !isGlowEnabled() ) return; const U32 binSize = mElementList.size(); // If this is a non-diffuse pass or we have no objects to // render then tell the effect to skip rendering. if ( !state->isDiffusePass() || binSize == 0 ) { getGlowEffect()->setSkip( true ); return; } GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN ); GFXTransformSaver saver; // Tell the superclass we're about to render, preserve contents const bool isRenderingToTarget = _onPreRender( state, true ); // Clear all the buffers to black. GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0); // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); matrixSet.restoreSceneViewProjection(); // init loop data SceneData sgData; sgData.init( state, SceneData::GlowBin ); for( U32 j=0; j<binSize; ) { MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst); setupSGData( ri, sgData ); BaseMatInstance *mat = ri->matInst; GlowMaterialHook *hook = mat->getHook<GlowMaterialHook>(); if ( !hook ) { hook = new GlowMaterialHook( ri->matInst ); ri->matInst->addHook( hook ); } BaseMatInstance *glowMat = hook->getMatInstance(); U32 matListEnd = j; while( glowMat && glowMat->setupPass( state, sgData ) ) { U32 a; for( a=j; a<binSize; a++ ) { MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst); if ( newPassNeeded( ri, passRI ) ) break; matrixSet.setWorld(*passRI->objectToWorld); matrixSet.setView(*passRI->worldToCamera); matrixSet.setProjection(*passRI->projection); glowMat->setTransforms(matrixSet, state); glowMat->setSceneInfo(state, sgData); glowMat->setBuffers(passRI->vertBuff, passRI->primBuff); if ( passRI->prim ) GFX->drawPrimitive( *passRI->prim ); else GFX->drawPrimitive( passRI->primBuffIndex ); } matListEnd = a; setupSGData( ri, sgData ); } // force increment if none happened, otherwise go to end of batch j = ( j == matListEnd ) ? j+1 : matListEnd; } // Finish up. if ( isRenderingToTarget ) _onPostRender(); // Make sure the effect is gonna render. getGlowEffect()->setSkip( false ); }
void RenderTranslucentMgr::render( SceneRenderState *state ) { PROFILE_SCOPE(RenderTranslucentMgr_render); // Early out if nothing to draw. if(!mElementList.size()) return; GFXDEBUGEVENT_SCOPE(RenderTranslucentMgr_Render, ColorI::BLUE); // Find the particle render manager (if we don't have it) if(mParticleRenderMgr == NULL) { RenderPassManager *rpm = state->getRenderPass(); for( U32 i = 0; i < rpm->getManagerCount(); i++ ) { RenderBinManager *bin = rpm->getManager(i); if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles ) { mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin); break; } } } GFXTransformSaver saver; SceneData sgData; sgData.init( state ); GFXVertexBuffer * lastVB = NULL; GFXPrimitiveBuffer * lastPB = NULL; // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); matrixSet.restoreSceneViewProjection(); U32 binSize = mElementList.size(); for( U32 j=0; j<binSize; ) { RenderInst *baseRI = mElementList[j].inst; U32 matListEnd = j; // render these separately... if ( baseRI->type == RenderPassManager::RIT_ObjectTranslucent ) { ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI); objRI->renderDelegate( objRI, state, NULL ); lastVB = NULL; lastPB = NULL; j++; continue; } //Volumetric Fog Add else if (baseRI->type == RenderPassManager::RIT_VolumetricFog) { ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI); objRI->renderDelegate(objRI,state,NULL); lastVB = NULL; lastPB = NULL; j++; continue; } //Volumetric Fog Add else if ( baseRI->type == RenderPassManager::RIT_Particle ) { ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(baseRI); // Tell Particle RM to draw the system. (This allows the particle render manager // to manage drawing offscreen particle systems, and allows the systems // to be composited back into the scene with proper translucent // sorting order) mParticleRenderMgr->renderInstance(ri, state); lastVB = NULL; // no longer valid, null it lastPB = NULL; // no longer valid, null it j++; continue; } else if ( baseRI->type == RenderPassManager::RIT_Translucent ) { MeshRenderInst* ri = static_cast<MeshRenderInst*>(baseRI); BaseMatInstance *mat = ri->matInst; setupSGData( ri, sgData ); while( mat->setupPass( state, sgData ) ) { U32 a; for( a=j; a<binSize; a++ ) { RenderInst* nextRI = mElementList[a].inst; if ( nextRI->type != RenderPassManager::RIT_Translucent ) break; MeshRenderInst *passRI = static_cast<MeshRenderInst*>(nextRI); // Check to see if we need to break this batch. if ( newPassNeeded( ri, passRI ) ) break; // Z sorting and stuff is still not working in this mgr... setupSGData( passRI, sgData ); mat->setSceneInfo(state, sgData); matrixSet.setWorld(*passRI->objectToWorld); matrixSet.setView(*passRI->worldToCamera); matrixSet.setProjection(*passRI->projection); mat->setTransforms(matrixSet, state); // If we're instanced then don't render yet. if ( mat->isInstanced() ) { // Let the material increment the instance buffer, but // break the batch if it runs out of room for more. if ( !mat->stepInstance() ) { a++; break; } continue; } // Setup the vertex and index buffers. mat->setBuffers( passRI->vertBuff, passRI->primBuff ); // Render this sucker. if ( passRI->prim ) GFX->drawPrimitive( *passRI->prim ); else GFX->drawPrimitive( passRI->primBuffIndex ); } // Draw the instanced batch. if ( mat->isInstanced() ) { // Sets the buffers including the instancing stream. mat->setBuffers( ri->vertBuff, ri->primBuff ); // Render the instanced stream. if ( ri->prim ) GFX->drawPrimitive( *ri->prim ); else GFX->drawPrimitive( ri->primBuffIndex ); } matListEnd = a; } // force increment if none happened, otherwise go to end of batch j = ( j == matListEnd ) ? j+1 : matListEnd; } } }
void RenderGlowMgr::render( SceneRenderState *state ) { PROFILE_SCOPE( RenderGlowMgr_Render ); if ( !isGlowEnabled() ) return; const U32 binSize = mElementList.size(); // If this is a non-diffuse pass or we have no objects to // render then tell the effect to skip rendering. if ( !state->isDiffusePass() || binSize == 0 ) { getGlowEffect()->setSkip( true ); return; } GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN ); GFXTransformSaver saver; // Respect the current viewport mNamedTarget.setViewport(GFX->getViewport()); // Tell the superclass we're about to render, preserve contents const bool isRenderingToTarget = _onPreRender( state, true ); // Clear all the buffers to black. GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0); // Restore transforms MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); matrixSet.restoreSceneViewProjection(); // init loop data SceneData sgData; sgData.init( state, SceneData::GlowBin ); for( U32 j=0; j<binSize; ) { RenderInst *_ri = mElementList[j].inst; if(_ri->type == RenderPassManager::RIT_Particle) { // Find the particle render manager (if we don't have it) if(mParticleRenderMgr == NULL) { RenderPassManager *rpm = state->getRenderPass(); for( U32 i = 0; i < rpm->getManagerCount(); i++ ) { RenderBinManager *bin = rpm->getManager(i); if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles ) { mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin); break; } } } ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(_ri); GFX->setStateBlock(mParticleRenderMgr->_getHighResStateBlock(ri)); mParticleRenderMgr->_getShaderConsts().mShaderConsts->setSafe(mParticleRenderMgr->_getShaderConsts().mModelViewProjSC, *ri->modelViewProj); mParticleRenderMgr->renderParticle(ri, state); j++; continue; } MeshRenderInst *ri = static_cast<MeshRenderInst*>(_ri); setupSGData( ri, sgData ); BaseMatInstance *mat = ri->matInst; GlowMaterialHook *hook = mat->getHook<GlowMaterialHook>(); if ( !hook ) { hook = new GlowMaterialHook( ri->matInst ); ri->matInst->addHook( hook ); } BaseMatInstance *glowMat = hook->getMatInstance(); U32 matListEnd = j; while( glowMat && glowMat->setupPass( state, sgData ) ) { U32 a; for( a=j; a<binSize; a++ ) { if (mElementList[a].inst->type == RenderPassManager::RIT_Particle) break; MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst); if ( newPassNeeded( ri, passRI ) ) break; matrixSet.setWorld(*passRI->objectToWorld); matrixSet.setView(*passRI->worldToCamera); matrixSet.setProjection(*passRI->projection); glowMat->setTransforms(matrixSet, state); glowMat->setSceneInfo(state, sgData); glowMat->setBuffers(passRI->vertBuff, passRI->primBuff); if ( passRI->prim ) GFX->drawPrimitive( *passRI->prim ); else GFX->drawPrimitive( passRI->primBuffIndex ); } matListEnd = a; setupSGData( ri, sgData ); } // force increment if none happened, otherwise go to end of batch j = ( j == matListEnd ) ? j+1 : matListEnd; } // Finish up. if ( isRenderingToTarget ) _onPostRender(); // Make sure the effect is gonna render. getGlowEffect()->setSkip( false ); }
void WaterPlane::innerRender( SceneRenderState *state ) { GFXDEBUGEVENT_SCOPE( WaterPlane_innerRender, ColorI( 255, 0, 0 ) ); const Point3F &camPosition = state->getCameraPosition(); Point3F rvec, fvec, uvec, pos; const MatrixF &objMat = getTransform(); //getRenderTransform(); const MatrixF &camMat = state->getCameraTransform(); MatrixF renderMat( true ); camMat.getColumn( 1, &fvec ); uvec.set( 0, 0, 1 ); rvec = mCross( fvec, uvec ); rvec.normalize(); fvec = mCross( uvec, rvec ); pos = camPosition; pos.z = objMat.getPosition().z; renderMat.setColumn( 0, rvec ); renderMat.setColumn( 1, fvec ); renderMat.setColumn( 2, uvec ); renderMat.setColumn( 3, pos ); setRenderTransform( renderMat ); // Setup SceneData SceneData sgData = setupSceneGraphInfo( state ); // set the material S32 matIdx = getMaterialIndex( camPosition ); if ( !initMaterial( matIdx ) ) return; BaseMatInstance *mat = mMatInstances[matIdx]; WaterMatParams matParams = mMatParamHandles[matIdx]; // render the geometry if ( mat ) { // setup proj/world transform mMatrixSet->restoreSceneViewProjection(); mMatrixSet->setWorld(getRenderTransform()); setShaderParams( state, mat, matParams ); while( mat->setupPass( state, sgData ) ) { mat->setSceneInfo(state, sgData); mat->setTransforms(*mMatrixSet, state, sgData); setCustomTextures( matIdx, mat->getCurPass(), matParams ); // set vert/prim buffer GFX->setVertexBuffer( mVertBuff ); GFX->setPrimitiveBuffer( mPrimBuff ); GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount ); } } }