renderMeshMgr.cpp
Engine/source/renderInstance/renderMeshMgr.cpp
Public Functions
ConsoleDocClass(RenderMeshMgr , "@brief A <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> mesh <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n\n</a>" "This is the primary <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin in Torque which does most of the " "work of rendering DTS shapes and arbitrary mesh geometry. It knows " "how <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> mesh instances using materials and supports hardware mesh " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">instancing.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(RenderMeshMgr , "@brief A <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> mesh <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">rendering.\n\n</a>" "This is the primary <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> bin in Torque which does most of the " "work of rendering DTS shapes and arbitrary mesh geometry. It knows " "how <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> mesh instances using materials and supports hardware mesh " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">instancing.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )
IMPLEMENT_CONOBJECT(RenderMeshMgr )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "renderInstance/renderMeshMgr.h" 26 27#include "console/consoleTypes.h" 28#include "gfx/gfxTransformSaver.h" 29#include "gfx/gfxPrimitiveBuffer.h" 30#include "materials/sceneData.h" 31#include "materials/processedMaterial.h" 32#include "materials/materialManager.h" 33#include "scene/sceneRenderState.h" 34#include "gfx/gfxDebugEvent.h" 35#include "math/util/matrixSet.h" 36 37 38IMPLEMENT_CONOBJECT(RenderMeshMgr); 39 40ConsoleDocClass( RenderMeshMgr, 41 "@brief A render bin for mesh rendering.\n\n" 42 "This is the primary render bin in Torque which does most of the " 43 "work of rendering DTS shapes and arbitrary mesh geometry. It knows " 44 "how to render mesh instances using materials and supports hardware mesh " 45 "instancing.\n\n" 46 "@ingroup RenderBin\n" ); 47 48 49RenderMeshMgr::RenderMeshMgr() 50: RenderBinManager(RenderPassManager::RIT_Mesh, 1.0f, 1.0f) 51{ 52} 53 54RenderMeshMgr::RenderMeshMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder) 55 : RenderBinManager(riType, renderOrder, processAddOrder) 56{ 57} 58 59void RenderMeshMgr::init() 60{ 61 GFXStateBlockDesc d; 62 63 d.cullDefined = true; 64 d.cullMode = GFXCullCCW; 65 d.samplersDefined = true; 66 d.samplers[0] = GFXSamplerStateDesc::getWrapLinear(); 67 68 mNormalSB = GFX->createStateBlock(d); 69 70 d.cullMode = GFXCullCW; 71 mReflectSB = GFX->createStateBlock(d); 72} 73 74void RenderMeshMgr::initPersistFields() 75{ 76 Parent::initPersistFields(); 77} 78 79//----------------------------------------------------------------------------- 80// add element 81//----------------------------------------------------------------------------- 82void RenderMeshMgr::addElement( RenderInst *inst ) 83{ 84 // If this instance is translucent handle it in RenderTranslucentMgr 85 if (inst->translucentSort) 86 return; 87 88 AssertFatal( inst->defaultKey != 0, "RenderMeshMgr::addElement() - Got null sort key... did you forget to set it?" ); 89 90 internalAddElement(inst); 91} 92 93//----------------------------------------------------------------------------- 94// render 95//----------------------------------------------------------------------------- 96void RenderMeshMgr::render(SceneRenderState * state) 97{ 98 PROFILE_SCOPE(RenderMeshMgr_render); 99 100 // Early out if nothing to draw. 101 if(!mElementList.size()) 102 return; 103 104 105 GFXDEBUGEVENT_SCOPE( RenderMeshMgr_Render, ColorI::GREEN ); 106 107 // Automagically save & restore our viewport and transforms. 108 GFXTransformSaver saver; 109 110 // Restore transforms 111 MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); 112 matrixSet.restoreSceneViewProjection(); 113 114 // init loop data 115 GFXTextureObject *lastLM = NULL; 116 GFXCubemap *lastCubemap = NULL; 117 GFXTextureObject *lastReflectTex = NULL; 118 GFXTextureObject *lastMiscTex = NULL; 119 GFXTextureObject *lastAccuTex = NULL; 120 121 SceneData sgData; 122 sgData.init( state ); 123 124 U32 binSize = mElementList.size(); 125 126 for( U32 j=0; j<binSize; ) 127 { 128 MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst); 129 130 setupSGData( ri, sgData ); 131 BaseMatInstance *mat = ri->matInst; 132 133 // If we have an override delegate then give it a 134 // chance to swap the material with another. 135 if ( mMatOverrideDelegate ) 136 { 137 mat = mMatOverrideDelegate( mat ); 138 if ( !mat ) 139 { 140 j++; 141 continue; 142 } 143 } 144 145 if( !mat ) 146 mat = MATMGR->getWarningMatInstance(); 147 148 // Check if bin is disabled in advanced lighting. 149 // Allow forward rendering pass on custom materials. 150 151 if ( ( MATMGR->getDeferredEnabled() && mBasicOnly && !mat->isCustomMaterial() ) ) 152 { 153 j++; 154 continue; 155 } 156 157 U32 matListEnd = j; 158 lastMiscTex = sgData.miscTex; 159 U32 a; 160 161 while( mat && mat->setupPass(state, sgData ) ) 162 { 163 for( a=j; a<binSize; a++ ) 164 { 165 MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst); 166 167 // Check to see if we need to break this batch. 168 if ( newPassNeeded( ri, passRI ) || 169 lastMiscTex != passRI->miscTex ) 170 { 171 lastLM = NULL; 172 break; 173 } 174 175 matrixSet.setWorld(*passRI->objectToWorld); 176 matrixSet.setView(*passRI->worldToCamera); 177 matrixSet.setProjection(*passRI->projection); 178 mat->setTransforms(matrixSet, state); 179 180 // Setup HW skinning transforms if applicable 181 if (mat->usesHardwareSkinning()) 182 { 183 mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount); 184 } 185 186 //push along any overriden fields that are instance-specific as well 187 if (passRI->mCustomShaderData.size() > 0) 188 { 189 mat->setCustomShaderData(passRI->mCustomShaderData); 190 } 191 192 setupSGData( passRI, sgData ); 193 mat->setSceneInfo( state, sgData ); 194 195 // If we're instanced then don't render yet. 196 if ( mat->isInstanced() ) 197 { 198 // Let the material increment the instance buffer, but 199 // break the batch if it runs out of room for more. 200 if ( !mat->stepInstance() ) 201 { 202 a++; 203 break; 204 } 205 206 continue; 207 } 208 209 // TODO: This could proably be done in a cleaner way. 210 // 211 // This section of code is dangerous, it overwrites the 212 // lightmap values in sgData. This could be a problem when multiple 213 // render instances use the same multi-pass material. When 214 // the first pass is done, setupPass() is called again on 215 // the material, but the lightmap data has been changed in 216 // sgData to the lightmaps in the last renderInstance rendered. 217 218 // This section sets the lightmap data for the current batch. 219 // For the first iteration, it sets the same lightmap data, 220 // however the redundancy will be caught by GFXDevice and not 221 // actually sent to the card. This is done for simplicity given 222 // the possible condition mentioned above. Better to set always 223 // than to get bogged down into special case detection. 224 //------------------------------------- 225 bool dirty = false; 226 227 // set the lightmaps if different 228 if( passRI->lightmap && passRI->lightmap != lastLM ) 229 { 230 sgData.lightmap = passRI->lightmap; 231 lastLM = passRI->lightmap; 232 dirty = true; 233 } 234 235 // set the cubemap if different. 236 if ( passRI->cubemap != lastCubemap ) 237 { 238 sgData.cubemap = passRI->cubemap; 239 lastCubemap = passRI->cubemap; 240 dirty = true; 241 } 242 243 if ( passRI->reflectTex != lastReflectTex ) 244 { 245 sgData.reflectTex = passRI->reflectTex; 246 lastReflectTex = passRI->reflectTex; 247 dirty = true; 248 } 249 250 // Update accumulation texture if it changed. 251 // Note: accumulation texture can be NULL, and must be updated. 252 if ( passRI->accuTex != lastAccuTex ) 253 { 254 sgData.accuTex = passRI->accuTex; 255 lastAccuTex = passRI->accuTex; 256 dirty = true; 257 } 258 259 if ( dirty ) 260 mat->setTextureStages( state, sgData ); 261 262 // Setup the vertex and index buffers. 263 mat->setBuffers( passRI->vertBuff, passRI->primBuff ); 264 265 // Render this sucker. 266 if ( passRI->prim ) 267 GFX->drawPrimitive( *passRI->prim ); 268 else 269 GFX->drawPrimitive( passRI->primBuffIndex ); 270 } 271 272 // Draw the instanced batch. 273 if ( mat->isInstanced() ) 274 { 275 // Sets the buffers including the instancing stream. 276 mat->setBuffers( ri->vertBuff, ri->primBuff ); 277 278 // Render the instanced stream. 279 if ( ri->prim ) 280 GFX->drawPrimitive( *ri->prim ); 281 else 282 GFX->drawPrimitive( ri->primBuffIndex ); 283 } 284 285 matListEnd = a; 286 } 287 288 // force increment if none happened, otherwise go to end of batch 289 j = ( j == matListEnd ) ? j+1 : matListEnd; 290 } 291} 292 293