renderTranslucentMgr.cpp
Engine/source/renderInstance/renderTranslucentMgr.cpp
Public Defines
define
HIGH_NUM() (((-1)/2) - 1)
Public Functions
ConsoleDocClass(RenderTranslucentMgr , "@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> rendering translucent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">meshes.\n\n</a>" "This bin is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> translucent <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> mesh instances and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> object " "instances. It is generally ordered late in the <a href="/coding/class/classrenderpassmanager/">RenderPassManager</a> after all opaque " "geometry <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bins.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )
Detailed Description
Public Defines
HIGH_NUM() (((-1)/2) - 1)
Public Functions
ConsoleDocClass(RenderTranslucentMgr , "@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> rendering translucent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">meshes.\n\n</a>" "This bin is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> translucent <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> mesh instances and <a href="/coding/file/editortool_8cpp/#editortool_8cpp_1a4cb041169a32ea3d4cacadbb955e06b4">render</a> object " "instances. It is generally ordered late in the <a href="/coding/class/classrenderpassmanager/">RenderPassManager</a> after all opaque " "geometry <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">bins.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RenderBin\n</a>" )
IMPLEMENT_CONOBJECT(RenderTranslucentMgr )
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/renderTranslucentMgr.h" 26 27#include "materials/sceneData.h" 28#include "scene/sceneManager.h" 29#include "scene/sceneObject.h" 30#include "scene/sceneRenderState.h" 31#include "materials/matInstance.h" 32#include "gfx/gfxPrimitiveBuffer.h" 33#include "gfx/gfxTransformSaver.h" 34#include "gfx/gfxDebugEvent.h" 35#include "renderInstance/renderParticleMgr.h" 36#include "math/util/matrixSet.h" 37 38#define HIGH_NUM ((U32(-1)/2) - 1) 39 40IMPLEMENT_CONOBJECT(RenderTranslucentMgr); 41 42ConsoleDocClass( RenderTranslucentMgr, 43 "@brief A render bin for rendering translucent meshes.\n\n" 44 "This bin is used to render translucent render mesh instances and render object " 45 "instances. It is generally ordered late in the RenderPassManager after all opaque " 46 "geometry bins.\n\n" 47 "@ingroup RenderBin\n" ); 48 49 50RenderTranslucentMgr::RenderTranslucentMgr() 51 : RenderBinManager( RenderPassManager::RIT_Translucent, 1.0f, 1.0f ), mParticleRenderMgr(NULL) 52{ 53 notifyType( RenderPassManager::RIT_ObjectTranslucent ); 54 notifyType( RenderPassManager::RIT_Particle ); 55 notifyType( RenderPassManager::RIT_VolumetricFog); 56} 57 58RenderTranslucentMgr::~RenderTranslucentMgr() 59{ 60} 61 62void RenderTranslucentMgr::setupSGData(MeshRenderInst *ri, SceneData &data ) 63{ 64 Parent::setupSGData( ri, data ); 65 66 // We do not support these in the translucent bin. 67 data.backBuffTex = NULL; 68 //data.cubemap = NULL; 69 data.lightmap = NULL; 70} 71 72void RenderTranslucentMgr::addElement( RenderInst *inst ) 73{ 74 // Right off the bat if its not translucent skip it. 75 if ( !inst->translucentSort ) 76 return; 77 78 // What type of instance is this. 79 const bool isMeshInst = inst->type == RenderPassManager::RIT_Translucent; 80 81 // Get its material if its a mesh. 82 BaseMatInstance* matInst = NULL; 83 if ( isMeshInst ) 84 matInst = static_cast<MeshRenderInst*>( inst )->matInst; 85 86 // If the material isn't translucent the skip it. 87 if ( matInst && !matInst->getMaterial()->isTranslucent() ) 88 return; 89 90 // We made it this far, add the instance. 91 mElementList.increment(); 92 MainSortElem& elem = mElementList.last(); 93 elem.inst = inst; 94 95 // Override the instances default key to be the sort distance. All 96 // the pointer dereferencing is in there to prevent us from losing 97 // information when converting to a U32. 98 elem.key = *((U32*)&inst->sortDistSq); 99 100 AssertFatal( inst->defaultKey != 0, "RenderTranslucentMgr::addElement() - Got null sort key... did you forget to set it?" ); 101 102 // Then use the instances primary key as our secondary key 103 elem.key2 = inst->defaultKey; 104} 105 106GFXStateBlockRef RenderTranslucentMgr::_getStateBlock( U8 transFlag ) 107{ 108 if ( mStateBlocks[transFlag].isValid() ) 109 return mStateBlocks[transFlag]; 110 111 GFXStateBlockDesc d; 112 113 d.cullDefined = true; 114 d.cullMode = GFXCullNone; 115 d.blendDefined = true; 116 d.blendEnable = true; 117 d.blendSrc = (GFXBlend)((transFlag >> 4) & 0x0f); 118 d.blendDest = (GFXBlend)(transFlag & 0x0f); 119 d.alphaDefined = true; 120 121 // See http://www.garagegames.com/mg/forums/result.thread.php?qt=81397 122 d.alphaTestEnable = (d.blendSrc == GFXBlendSrcAlpha && (d.blendDest == GFXBlendInvSrcAlpha || d.blendDest == GFXBlendOne)); 123 d.alphaTestRef = 1; 124 d.alphaTestFunc = GFXCmpGreaterEqual; 125 d.zDefined = true; 126 d.zWriteEnable = false; 127 d.samplersDefined = true; 128 d.samplers[0] = GFXSamplerStateDesc::getClampLinear(); 129 130 mStateBlocks[transFlag] = GFX->createStateBlock(d); 131 return mStateBlocks[transFlag]; 132} 133 134void RenderTranslucentMgr::render( SceneRenderState *state ) 135{ 136 PROFILE_SCOPE(RenderTranslucentMgr_render); 137 138 // Early out if nothing to draw. 139 if(!mElementList.size()) 140 return; 141 142 GFXDEBUGEVENT_SCOPE(RenderTranslucentMgr_Render, ColorI::BLUE); 143 144 // init loop data 145 GFXTextureObject *lastLM = NULL; 146 GFXCubemap *lastCubemap = NULL; 147 GFXTextureObject *lastReflectTex = NULL; 148 GFXTextureObject *lastMiscTex = NULL; 149 GFXTextureObject *lastAccuTex = NULL; 150 151 // Find the particle render manager (if we don't have it) 152 if(mParticleRenderMgr == NULL) 153 { 154 RenderPassManager *rpm = state->getRenderPass(); 155 for( U32 i = 0; i < rpm->getManagerCount(); i++ ) 156 { 157 RenderBinManager *bin = rpm->getManager(i); 158 if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles ) 159 { 160 mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin); 161 break; 162 } 163 } 164 } 165 166 GFXTransformSaver saver; 167 168 SceneData sgData; 169 sgData.init( state ); 170 171 GFXVertexBuffer * lastVB = NULL; 172 GFXPrimitiveBuffer * lastPB = NULL; 173 174 // Restore transforms 175 MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); 176 matrixSet.restoreSceneViewProjection(); 177 178 U32 binSize = mElementList.size(); 179 for( U32 j=0; j<binSize; ) 180 { 181 RenderInst *baseRI = mElementList[j].inst; 182 183 U32 matListEnd = j; 184 185 // render these separately... 186 if ( baseRI->type == RenderPassManager::RIT_ObjectTranslucent ) 187 { 188 ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI); 189 objRI->renderDelegate( objRI, state, NULL ); 190 191 lastVB = NULL; 192 lastPB = NULL; 193 j++; 194 continue; 195 } 196 else if (baseRI->type == RenderPassManager::RIT_VolumetricFog) 197 { 198 ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI); 199 objRI->renderDelegate(objRI, state, NULL); 200 lastVB = NULL; 201 lastPB = NULL; 202 j++; 203 continue; 204 } 205 else if ( baseRI->type == RenderPassManager::RIT_Particle ) 206 { 207 ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(baseRI); 208 209 // Tell Particle RM to draw the system. (This allows the particle render manager 210 // to manage drawing offscreen particle systems, and allows the systems 211 // to be composited back into the scene with proper translucent 212 // sorting order) 213 mParticleRenderMgr->renderInstance(ri, state); 214 215 lastVB = NULL; // no longer valid, null it 216 lastPB = NULL; // no longer valid, null it 217 218 j++; 219 continue; 220 } 221 else if ( baseRI->type == RenderPassManager::RIT_Translucent ) 222 { 223 MeshRenderInst* ri = static_cast<MeshRenderInst*>(baseRI); 224 BaseMatInstance *mat = ri->matInst; 225 226 setupSGData( ri, sgData ); 227 228 while( mat->setupPass( state, sgData ) ) 229 { 230 U32 a; 231 for( a=j; a<binSize; a++ ) 232 { 233 RenderInst* nextRI = mElementList[a].inst; 234 if ( nextRI->type != RenderPassManager::RIT_Translucent ) 235 break; 236 237 MeshRenderInst *passRI = static_cast<MeshRenderInst*>(nextRI); 238 239 // Check to see if we need to break this batch. 240 if ( newPassNeeded( ri, passRI ) ) 241 break; 242 243 // Z sorting and stuff is still not working in this mgr... 244 setupSGData( passRI, sgData ); 245 mat->setSceneInfo(state, sgData); 246 matrixSet.setWorld(*passRI->objectToWorld); 247 matrixSet.setView(*passRI->worldToCamera); 248 matrixSet.setProjection(*passRI->projection); 249 mat->setTransforms(matrixSet, state); 250 251 // Setup HW skinning transforms if applicable 252 if (mat->usesHardwareSkinning()) 253 { 254 mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount); 255 } 256 257 //push along any overriden fields that are instance-specific as well 258 if (passRI->mCustomShaderData.size() > 0) 259 { 260 mat->setCustomShaderData(passRI->mCustomShaderData); 261 } 262 263 // If we're instanced then don't render yet. 264 if ( mat->isInstanced() ) 265 { 266 // Let the material increment the instance buffer, but 267 // break the batch if it runs out of room for more. 268 if ( !mat->stepInstance() ) 269 { 270 a++; 271 break; 272 } 273 274 continue; 275 } 276 277 bool dirty = false; 278 279 // set the lightmaps if different 280 if (passRI->lightmap && passRI->lightmap != lastLM) 281 { 282 sgData.lightmap = passRI->lightmap; 283 lastLM = passRI->lightmap; 284 dirty = true; 285 } 286 287 // set the cubemap if different. 288 if (passRI->cubemap != lastCubemap) 289 { 290 sgData.cubemap = passRI->cubemap; 291 lastCubemap = passRI->cubemap; 292 dirty = true; 293 } 294 295 if (passRI->reflectTex != lastReflectTex) 296 { 297 sgData.reflectTex = passRI->reflectTex; 298 lastReflectTex = passRI->reflectTex; 299 dirty = true; 300 } 301 302 // Update accumulation texture if it changed. 303 // Note: accumulation texture can be NULL, and must be updated. 304 if (passRI->accuTex != lastAccuTex) 305 { 306 sgData.accuTex = passRI->accuTex; 307 lastAccuTex = passRI->accuTex; 308 dirty = true; 309 } 310 311 if (dirty) 312 mat->setTextureStages(state, sgData); 313 314 // Setup the vertex and index buffers. 315 mat->setBuffers( passRI->vertBuff, passRI->primBuff ); 316 317 // Render this sucker. 318 if ( passRI->prim ) 319 GFX->drawPrimitive( *passRI->prim ); 320 else 321 GFX->drawPrimitive( passRI->primBuffIndex ); 322 } 323 324 // Draw the instanced batch. 325 if ( mat->isInstanced() ) 326 { 327 // Sets the buffers including the instancing stream. 328 mat->setBuffers( ri->vertBuff, ri->primBuff ); 329 330 // Render the instanced stream. 331 if ( ri->prim ) 332 GFX->drawPrimitive( *ri->prim ); 333 else 334 GFX->drawPrimitive( ri->primBuffIndex ); 335 } 336 337 matListEnd = a; 338 } 339 340 // force increment if none happened, otherwise go to end of batch 341 j = ( j == matListEnd ) ? j+1 : matListEnd; 342 } 343 } 344} 345