| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 | //-----------------------------------------------------------------------------// Copyright (c) 2012 GarageGames, LLC//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS// IN THE SOFTWARE.//-----------------------------------------------------------------------------#include "platform/platform.h"#include "renderInstance/renderTranslucentMgr.h"#include "materials/sceneData.h"#include "scene/sceneManager.h"#include "scene/sceneObject.h"#include "scene/sceneRenderState.h"#include "materials/matInstance.h"#include "gfx/gfxPrimitiveBuffer.h"#include "gfx/gfxTransformSaver.h"#include "gfx/gfxDebugEvent.h"#include "renderInstance/renderParticleMgr.h"#include "math/util/matrixSet.h"#define HIGH_NUM ((U32(-1)/2) - 1)IMPLEMENT_CONOBJECT(RenderTranslucentMgr);ConsoleDocClass( RenderTranslucentMgr,    "@brief A render bin for rendering translucent meshes.\n\n"   "This bin is used to render translucent render mesh instances and render object "   "instances. It is generally ordered late in the RenderPassManager after all opaque "   "geometry bins.\n\n"   "@ingroup RenderBin\n" );RenderTranslucentMgr::RenderTranslucentMgr()   :  RenderBinManager( RenderPassManager::RIT_Translucent, 1.0f, 1.0f ), mParticleRenderMgr(NULL){   notifyType( RenderPassManager::RIT_ObjectTranslucent );   notifyType( RenderPassManager::RIT_Particle );   notifyType( RenderPassManager::RIT_VolumetricFog);}RenderTranslucentMgr::~RenderTranslucentMgr(){}void RenderTranslucentMgr::setupSGData(MeshRenderInst *ri, SceneData &data ){   Parent::setupSGData( ri, data );   // We do not support these in the translucent bin.   data.backBuffTex = NULL;   //data.cubemap = NULL;      data.lightmap = NULL;}void RenderTranslucentMgr::addElement( RenderInst *inst ){   // Right off the bat if its not translucent skip it.   if ( !inst->translucentSort )      return;   // What type of instance is this.   const bool isMeshInst = inst->type == RenderPassManager::RIT_Translucent;   // Get its material if its a mesh.   BaseMatInstance* matInst = NULL;   if ( isMeshInst )      matInst = static_cast<MeshRenderInst*>( inst )->matInst;   // If the material isn't translucent the skip it.   if ( matInst && !matInst->getMaterial()->isTranslucent() )      return;   // We made it this far, add the instance.   mElementList.increment();   MainSortElem& elem = mElementList.last();   elem.inst = inst;   // Override the instances default key to be the sort distance. All    // the pointer dereferencing is in there to prevent us from losing   // information when converting to a U32.   elem.key = *((U32*)&inst->sortDistSq);   AssertFatal( inst->defaultKey != 0, "RenderTranslucentMgr::addElement() - Got null sort key... did you forget to set it?" );   // Then use the instances primary key as our secondary key   elem.key2 = inst->defaultKey;}GFXStateBlockRef RenderTranslucentMgr::_getStateBlock( U8 transFlag ){   if ( mStateBlocks[transFlag].isValid() )      return mStateBlocks[transFlag];   GFXStateBlockDesc d;   d.cullDefined = true;   d.cullMode = GFXCullNone;   d.blendDefined = true;   d.blendEnable = true;   d.blendSrc = (GFXBlend)((transFlag >> 4) & 0x0f);    d.blendDest = (GFXBlend)(transFlag & 0x0f);   d.alphaDefined = true;      // See http://www.garagegames.com/mg/forums/result.thread.php?qt=81397   d.alphaTestEnable = (d.blendSrc == GFXBlendSrcAlpha && (d.blendDest == GFXBlendInvSrcAlpha || d.blendDest == GFXBlendOne));   d.alphaTestRef = 1;   d.alphaTestFunc = GFXCmpGreaterEqual;   d.zDefined = true;   d.zWriteEnable = false;   d.samplersDefined = true;   d.samplers[0] = GFXSamplerStateDesc::getClampLinear();   mStateBlocks[transFlag] = GFX->createStateBlock(d);   return mStateBlocks[transFlag];}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);   // init loop data   GFXTextureObject *lastLM = NULL;   GFXCubemap *lastCubemap = NULL;   GFXTextureObject *lastReflectTex = NULL;   GFXTextureObject *lastAccuTex = NULL;   // 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;      }      else if (baseRI->type == RenderPassManager::RIT_VolumetricFog)	   {	      ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI);	      objRI->renderDelegate(objRI, state, NULL);	      lastVB = NULL;	      lastPB = NULL;	      j++;	      continue;	   }      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);               // Setup HW skinning transforms if applicable               if (mat->usesHardwareSkinning())               {                  mat->setNodeTransforms(passRI->mNodeTransforms, passRI->mNodeTransformCount);               }			   //push along any overriden fields that are instance-specific as well			   if (passRI->mCustomShaderData.size() > 0)			   {				   mat->setCustomShaderData(passRI->mCustomShaderData);			   }               // 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;               }               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;               }               // Update accumulation texture if it changed.               // Note: accumulation texture can be NULL, and must be updated.               if (passRI->accuTex != lastAccuTex)               {                  sgData.accuTex = passRI->accuTex;                  lastAccuTex = passRI->accuTex;                  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;      }   }}
 |