コード例 #1
0
void VTerrainDecorationEntityModel::RenderBatchIR(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount, RenderMode_e eRenderMode)
{
  // IR Rendering
  VTerrainDecorationModelManager* pManager = (VTerrainDecorationModelManager *)GetParentManager();
  VShaderEffectLib* pEffectLib = pManager->GetInfraredShaderLib();
  if (iCount > 0 && pManager->m_iInstancingBatchCount > 0 && pEffectLib != NULL)
  {
    int iMaxInstanceCount, iInstanceStreamMask;
    VisSurface_cl* pSurface = m_spMesh->GetSurface(0);

    if (m_spInstancingTechIRPrePass == NULL)
    {
      // lazy IR shader init
      RecreateIRShaders(pSurface, pEffectLib);
    }
    if (m_spInstancingTechIRPrePass == NULL || m_spInstancingTechIRMainPass == NULL)
      return;

    const int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount();
    const int iVertexCount = m_spModelMesh->GetVertexCount();
    const VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType();

    bool bPrePass = (eRenderMode == RENDER_MODE_IR_PREPASS);
    VCompiledShaderPass* pShader = bPrePass? m_spInstancingTechIRPrePass->GetShader(0) : m_spInstancingTechIRMainPass->GetShader(0);
    
    const int iStreamMask = m_spModelMesh->GetStreamMask() & (pShader->GetStreamMask() | VERTEX_STREAM_INDEXBUFFER);
    VisMeshBuffer_cl* pInstanceMesh = pManager->GetInstanceBuffer(iMaxInstanceCount, iInstanceStreamMask);
    iInstanceStreamMask &= pShader->GetStreamMask();

    // perform the rendering
    Vision::RenderLoopHelper.BeginMeshRendering();

    Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface, pShader);

    if (!bPrePass || pSurface->GetTransparencyType() != VIS_TRANSP_NONE)
      Vision::RenderLoopHelper.BindMeshTexture(pSurface->GetBaseTextureObject(), 0, NULL);

    while (iCount > 0)
    {
      int iRenderCount = hkvMath::Min(iCount, iMaxInstanceCount);

      // fill the instance buffer:
      {
        VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);

        VModelInstanceData_t* pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE, 0, iRenderCount);
        for (int i = 0; i < iRenderCount; i++, pInstList++, pDest++)
          pDest->Set(*pInstList[0]);
        pInstanceMesh->UnLockVertices();
      }

      iCount -= iRenderCount;

      RENDER_INSTANCES(iRenderCount, iStreamMask);
    }

    Vision::RenderLoopHelper.EndMeshRendering();
  }
}
コード例 #2
0
void VTerrainDecorationEntityModel::UpdateParameter()
{
  VBaseMesh *pOldMesh = m_spMesh;
  m_spMesh = Vision::Game.LoadDynamicMesh(GetFilename(),true);

  m_bNeedsLightmap = false;
  m_iLightmapSampler = -1;
  bool bSupportsDepthRendering = true;
  bool bSupportsShadowmapRendering = true;
  if (m_spMesh)
  {
    m_spMesh->GetVisibilityBoundingBox(m_LocalBBox);

    // check shader requirements
    for (int i=0;i<(int)m_spMesh->GetSurfaceCount();i++)
    {
      VisSurface_cl *pSrf = m_spMesh->GetSurface(i);
      if (pSrf->m_spDepthFill==NULL)
        bSupportsDepthRendering = false;
      if (pSrf->m_spShadowmapFill==NULL)
        bSupportsShadowmapRendering = false;

      VCompiledTechnique *pSrfTech = pSrf->GetTechnique();
      
      if (!pSrfTech)
        continue;
      for (int j=0;j<pSrfTech->GetShaderCount();j++)
      {
        const VCompiledShaderPass *pShader = pSrfTech->GetShader(j);
        const int iActiveSamplerCount = (int)pShader->GetActiveSamplerCount(VSS_PixelShader);
        for (int k=0;k<iActiveSamplerCount;k++)
        {
          const VStateGroupTexture *pStateGroupTexture = pShader->GetStateGroupTexture(VSS_PixelShader, k);
          VASSERT(pStateGroupTexture != NULL);
          if (pStateGroupTexture->m_cTextureType == TEXTURETYPE_LIGHTMAP)
          {
            m_iLightmapSampler = k;
            m_bNeedsLightmap = true;
          }
        }
      }
    }
  }

  IVTerrainDecorationModel::UpdateParameter();

  if (pOldMesh != m_spMesh)
    ReapplyShaders();

  if (!bSupportsShadowmapRendering)
    m_iSupportedContextTypes &= ~(1<<VIS_CONTEXTUSAGE_DEPTHSHADOW);
  if (bSupportsDepthRendering)
    m_iSupportedContextTypes |= (1<<VIS_CONTEXTUSAGE_DEPTHFILL);

}
コード例 #3
0
// Simplified version of dynamic light rendering for mirrors
void MirrorRenderLoop_cl::DrawDynamicLight()
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::DrawDynamicLight");

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  VCompiledTechnique *pTechnique = NULL;

  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;

  // Get all visible light sources
  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;

  const VisLightSrcCollection_cl *pLightSourceCollection = pVisColl->GetVisibleLights();
  unsigned int i;
  unsigned int iNumLights = pLightSourceCollection->GetNumEntries();
  if (iNumLights == 0)
    return;

  // Set depth-stencil state
  VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);
  
  // For all visible lights...
  for (i=0; i<iNumLights; i++)
  {
    VisLightSource_cl *pLight = pLightSourceCollection->GetEntry(i);
    // We're only interested in dynamic lights
    if (!pLight->IsDynamic()) 
      continue;

    // Clear the collections of geo instances and entities, since we want to build them from scratch for each light
    s_LitEntityCollection.Clear();
    s_LitGeoInstanceCollection.Clear();

    // See which geometry types have to cast shadows
    int iReceiverFlags = GetLightReceiverFlags(pLight);

    // If nothing receives light from this light source, we can proceed to the next light.
    if (!iReceiverFlags)
      continue;

    // ***************** Create lists of illuminated scene elements *****************

    // If no shadows are cast, we simply illuminate all visible geometry within the range (spherical) of the light.
    VisEntityCollection_cl *pEntColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_MODELS)
      pEntColl = &s_LitEntityCollection;
    VisStaticGeometryInstanceCollection_cl *pGeoInstanceColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_PRIMITIVES)
    {
      pGeoInstanceColl = &s_LitGeoInstanceCollection;
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pGeoInstanceColl, pEntColl, NULL, *pLight);

    // For all illuminated entities: Render a dynamic lighting pass now.
    if (pLight->GetLightInfluenceBitMaskEntity())
    {
      int j;
      
      int iNumLitEntities = s_LitEntityCollection.GetNumEntries();

      Vision::RenderLoopHelper.BeginEntityRendering();

      for (j=0; j<iNumLitEntities; j++)
      {
        VisBaseEntity_cl *pEntity = s_LitEntityCollection.GetEntry(j);
        // Ignore foreground entities (they don't trivially support additive lighting)
        if (pEntity->IsObjectAlwaysInForegroundEnabled())
          continue;
        if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
          continue;
        if (!pVisColl->IsEntityVisible(pEntity))
          continue;
          
        VDynamicMesh *pMesh = pEntity->GetMesh();
          
        // Get list of all the surfaces in the model
        int iNumSubmeshes = pMesh->GetSubmeshCount();
        int iNumSurfaceShaders = 0;
        VisSurface_cl **ppSurfaceArray = pEntity->GetSurfaceArray();

        // For all the surfaces...
        for (int k=0; k<iNumSubmeshes; k++)
        {
          VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
          VASSERT(pSubmesh != NULL);
          VisSurface_cl* pSurface = &m_dummySurface; 
          VisSurface_cl* pMeshSurface = pSubmesh->m_pSurface;
          VASSERT(pMeshSurface != NULL);

          bool bHasManualTemplateShaderAssignment = pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Template 
            && pMeshSurface->GetMaterialTemplate() != NULL && pMeshSurface->GetMaterialTemplate()->HasManualAssignment();

          if (shaderMode == VisMirror_cl::AlwaysSurfaceShaders || 
            (shaderMode == VisMirror_cl::SimpleForAUTO && ( (pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Manual) || bHasManualTemplateShaderAssignment) ) )
          {
            pSurface = ppSurfaceArray[pSubmesh->m_iMaterialIndex]; // use the real surface
          }
          pTechnique = Vision::GetApplication()->GetShaderProvider()->GetDynamicLightShader(pLight, pSurface, true);
          if (pTechnique==NULL)
            continue;
            
          VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
          info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
        }
        // Finally, render the entity with a surface shader list.
        if (iNumSurfaceShaders>0)
          Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
      }

      Vision::RenderLoopHelper.EndEntityRendering();
    }

    // For all illuminated world primitives: Render a dynamic lighting pass now
    if (pLight->GetLightInfluenceBitMaskWorld() > 0)
    {
      // For all illuminated static geometry instances: Render a dynamic lighting pass now.
      int iNumLitGeoInstances = s_LitGeoInstanceCollection.GetNumEntries();

      s_RenderGeoInstanceCollection.Clear();

      // Render illuminated geometry instances. 
      for (int j=0; j < iNumLitGeoInstances; j++)
      {
        VisStaticGeometryInstance_cl *pGI = s_LitGeoInstanceCollection.GetEntry(j);

        if (pGI->GetSurface()==NULL || pGI->GetSurface()->IsFullbright())
          continue;
       
        // We have to append the primitive to our collection
        s_RenderGeoInstanceCollection.AppendEntry(pGI);
      }

      // render the collection
      const int iLitGeoCount = s_RenderGeoInstanceCollection.GetNumEntries();
      if (iLitGeoCount > 0)
      {
        VCompiledTechnique *pLastTech = NULL;
        VisSurface_cl* pLastSurface = NULL;
        m_CustomGeoInstances.EnsureSize(iLitGeoCount);
        m_CustomGeoInstances.Clear();

        for (int j=0; j < iLitGeoCount; j++)
        {
          VisStaticGeometryInstance_cl *pGI = s_RenderGeoInstanceCollection.GetEntry(j);

          GetLightShader (pLight, pGI, m_pMirror->m_eReflectionShaderMode, pLastSurface, pLastTech, pLastSurface, pTechnique);
          
          // The current technique has changed, so we have to render the previously gathered geometry.
          if (pLastTech != pTechnique)
          {
            if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
            {
              Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pLastTech->m_Shaders.GetAt(0) );
              m_CustomGeoInstances.Clear();
            }
            pLastTech = pTechnique;
          }
          m_CustomGeoInstances.AppendEntryFast(pGI);
        }
        // Render remaining geometry
        if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
        {
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pTechnique->m_Shaders.GetAt(0) );
        }

        s_RenderGeoInstanceCollection.Clear();
      }
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
コード例 #4
0
void VTerrainDecorationEntityModel::ReapplyShaders()
{
  m_spVegetationShaders = NULL;

  // set default material to vegetation (when AUTO mode is used):
  if (m_spMesh!=NULL)
  {

#if defined( HK_ANARCHY )
    const BOOL bUseDeferred = FALSE;
#else
    const BOOL bUseDeferred =  Vision::Renderer.IsRendererNodeOfType(V_RUNTIME_CLASS(VDeferredRenderingSystem));
#endif
    
    int iSubmeshCount = m_spMesh->GetSubmeshCount();
    for (int i=0;i<iSubmeshCount;i++)
    {
      VCompiledEffect *pVegetationFX = NULL;
      VBaseSubmesh *pSubmesh = m_spMesh->GetSubmesh(i);
      VisSurface_cl *pSurf = pSubmesh->GetSurface();
      if (m_spVegetationShaders==NULL)
        m_spVegetationShaders = new VisShaderSet_cl();

      if (pSurf->GetShaderMode()==VisSurface_cl::VSM_Auto)
      {
        char szParamStr[1024];
      
        const hkvAlignedBBox &bbox = m_spMesh->GetBoundingBox();
        float fBaseZ = bbox.isValid() ? -bbox.m_vMin.z : 0.f;
        sprintf(szParamStr,"MaterialParams=%.4f,%.4f,%.4f,%.4f;AlphaThreshold=%.3f;fBaseZ=%.2f", 
          pSurf->GetSpecularMultiplier(),
          pSurf->GetSpecularExponent(),
          pSurf->GetParallaxScale (), pSurf->GetParallaxBias (),
          pSurf->GetAlphaTestThreshold(),fBaseZ
          );

        if (bUseDeferred)
        {
          if (Vision::RenderLoopHelper.GetLightGrid()!=NULL)
          {
            VShaderEffectLib *pLib = Vision::Shaders.LoadShaderLibrary("\\Shaders\\DeferredShadingVegetationLG.ShaderLib", SHADERLIBFLAG_HIDDEN);
            pVegetationFX = Vision::Shaders.CreateEffect("DeferredVegetation_Wind_LG",szParamStr,EFFECTCREATEFLAG_NONE,pLib);
          } else
          {
            VShaderEffectLib *pLib = Vision::Shaders.LoadShaderLibrary("\\Shaders\\DeferredShadingVegetation.ShaderLib", SHADERLIBFLAG_HIDDEN);
            pVegetationFX = Vision::Shaders.CreateEffect("DeferredVegetation_Wind",szParamStr,EFFECTCREATEFLAG_NONE,pLib);
          }
        } else
        {
          BOOL bRes = Vision::Shaders.LoadShaderLibrary("\\Shaders\\TerrainVegetation.ShaderLib", SHADERLIBFLAG_HIDDEN) != NULL;
          if (pSurf->m_spNormalMap!=NULL)
          {
            if (pSurf->m_spSpecularMap!=NULL)
              pVegetationFX = Vision::Shaders.CreateEffect("VegetationNrmlSpec_Wind",szParamStr);
            else
              pVegetationFX = Vision::Shaders.CreateEffect("VegetationNrml_Wind",szParamStr);
          } 
          else
            pVegetationFX = Vision::Shaders.CreateEffect("Vegetation_Wind",szParamStr);
        }
      }
      
      if (pVegetationFX==NULL)
        pVegetationFX = pSurf->GetEffect();
      else
      {
        pSurf->SetEffect(pVegetationFX); // sets up depth technique etc.
        pSurf->SetShaderMode(VisSurface_cl::VSM_Auto);
      }
      if (pSurf->GetTechnique())
        m_spVegetationShaders->Add(pSubmesh, pSurf, pSurf->GetTechnique());
    }
  }

  if (m_spVegetationShaders==NULL)
    m_spVegetationShaders = m_spMesh->GetShaderSet();  // no clone


  // supports instancing at all?
#if defined (WIN32)
  m_spInstancingTech = NULL;
  m_spInstancingTechShadow = NULL;
  m_spInstancingTechIRPrePass = NULL;
  m_spInstancingTechIRMainPass = NULL;
  if (Vision::Renderer.SupportsInstancing() && m_bValidState && m_spVegetationShaders->Count()==1)
  {
    const VisDrawCallInfo_t &drawCall(m_spVegetationShaders->GetDrawCallList()[0]);
    VisSurface_cl *pMat = drawCall.GetSurface();
    bool bAnyInstancingShader = false;
    VCompiledEffect *pFX = pMat->m_spCurrentEffect;
    if (pFX) // checks whether the assigned shader effect holds an instancing version
    {
      VTechniqueConfig cfg;

#ifdef _VR_DX10
      if ((Vision::Renderer.GetRendererNode ()) && (Vision::Renderer.GetRendererNode ()->GetMultisampleMode() != VVIDEO_MULTISAMPLE_OFF))
        cfg.SetInclusionTags("Instancing;MSAA");
      else
#endif
      cfg.SetInclusionTags("Instancing");
      m_spInstancingTech = pFX->FindCompatibleTechnique(&cfg, Vision::Shaders.GetGlobalTechniqueConfig());
      if (m_spInstancingTech!=NULL && m_spInstancingTech->GetShaderCount()==1)
        bAnyInstancingShader = true;

      // shadowmap instancing?
      VTechniqueConfig cfg_shadow("Instancing;SpecificShadowmapFill",NULL);
      m_spInstancingTechShadow = pFX->FindCompatibleTechnique(&cfg_shadow, Vision::Shaders.GetGlobalTechniqueConfig());
      if (m_spInstancingTechShadow!=NULL && m_spInstancingTechShadow->GetShaderCount()==1)
        bAnyInstancingShader = true;
    }


    if (bAnyInstancingShader)
    {
      VisMBVertexDescriptor_t desc;
      int iIndexCount = m_spMesh->GetMeshBuffer()->GetIndexCount();
      VVertexBuffer* pVB = m_spMesh->GetMeshBuffer()->GetVertexBuffer();
      m_spMesh->GetMeshBuffer()->GetVertexDescriptor(desc);

      VIndexBuffer* pIB = m_spMesh->GetMeshBuffer()->GetIndexBuffer();

      m_spModelMesh = new VisMeshBuffer_cl();
      m_spModelMesh->SetVertexBuffer(pVB,desc,m_spMesh->GetNumOfVertices(),VIS_MEMUSAGE_STATIC, 0);
      m_spModelMesh->SetIndexBuffer(pIB,iIndexCount,pIB->GetUsageFlags(), 0);
      m_spModelMesh->SetPrimitiveCount(iIndexCount/3);
      m_spModelMesh->SetPrimitiveType(VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST);
      #ifdef HK_DEBUG
      m_spModelMesh->SetFilename("<TerrainDecorationEntity>");
      #endif
      m_iModelStreams = m_spModelMesh->GetStreamMask() & (m_spInstancingTech->GetShader(0)->GetStreamMask () | VERTEX_STREAM_INDEXBUFFER);
    }
  }
#endif
}
コード例 #5
0
void VMobileForwardRenderLoop::RenderLitGeometry(VisLightSource_cl *pLight, IVShadowMapComponent *pShadowMapComponent, bool bBasePass, bool bUsesLightClippingVolume, bool bEntities, bool bStaticGeometry)
{
  if (!pLight)
    return;

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VCompiledTechnique *pTechnique = NULL;
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  const hkvVec3 &vCamPos = pContext->GetCamera()->GetPosition();
 
  const float fFade = pLight->GetFadeWeight(vCamPos);

  VisStaticGeometryInstanceCollection_cl *pLitGeoInstanceCollection = NULL;
  VisEntityCollection_cl *pLitEntityCollection = NULL;

  if (bBasePass || pLight != m_pBasePassLight)
  {
    if (bStaticGeometry)
    {
      pLitGeoInstanceCollection = &s_LitGeoInstanceCollection;
      pLitGeoInstanceCollection->Clear();
    }
    if (bEntities)
    {
      pLitEntityCollection = &s_LitEntityCollection;
      pLitEntityCollection->Clear();
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pLitGeoInstanceCollection, pLitEntityCollection, NULL, *pLight);
  }
  else
  {
    if (bStaticGeometry)
      pLitGeoInstanceCollection = &m_AdditiveLitGeoInstanceCollection;
    if (bEntities)
      pLitEntityCollection = &m_AdditiveLitEntityCollection;
  }

#ifdef SUPPORTS_SHADOW_MAPS
  VShadowMapGenSpotDir *pShadowMapGenDir = NULL;
  if (pShadowMapComponent)
  {
    VShadowMapGenerator *pShadowMapGen = pShadowMapComponent->GetShadowMapGenerator();
    if (pShadowMapGen->GetProjectionType()==SHADOW_PROJECTION_ORTHOGRAPHIC)
      pShadowMapGenDir = static_cast<VShadowMapGenSpotDir*>(pShadowMapGen);
  }
#endif

  // Set the stencil render state for reading light clipping volume information
  if(bUsesLightClippingVolume)
  {
    const VLightClippingVolumeComponent* pLightClippingComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
    VASSERT(pLightClippingComponent != NULL && V_ARRAY_SIZE(m_lightClippingStencilStatesRead)==2);
    VisRenderStates_cl::SetDepthStencilState(m_lightClippingStencilStatesRead[pLightClippingComponent->GetClipHandedness()]);
  }
  else
    VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);

  // For all illuminated entities: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskEntity() != 0  && bEntities)
  {
    int iNumLitEntities = pLitEntityCollection->GetNumEntries();

    Vision::RenderLoopHelper.BeginEntityRendering();

    for (int j=0; j<iNumLitEntities; j++)
    {
      VisBaseEntity_cl *pEntity = pLitEntityCollection->GetEntry(j);

      if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
        continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();
      VisSurface_cl **ppSurfaces = pEntity->GetSurfaceArray();

      // Get list of all the surfaces in the model
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      int iNumSurfaceShaders = 0;

      // For all the surfaces...
      for (int k=0; k<iNumSubmeshes; k++)
      {
        VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
        VisSurface_cl *pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];

        // Full-bright surfaces can't be rendered in the compound base pass, since such surfaces are not illuminated. Since tagging
        // of already rendered geometry happens per entity instance, in case an entity contains full-bright surfaces, all surfaces 
        // of this entity have to be rendered in the normal rendering pipeline.
        const VisLightingMethod_e eLightingMethod = pSurface->GetLightingMode();
        if (bBasePass)
        {
          // Since entities can contain several surfaces with different lighting methods (full-bright, dynamic only, etc.), entities 
          // with full-bright surfaces have to be also added to the additive lit entity collection, in order to ensure rendering of 
          // dynamic only surfaces.
          if (eLightingMethod==VIS_LIGHTING_FULLBRIGHT)
          {
            iNumSurfaceShaders = 0;
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
            break; 
          }
        }
        else
        {
          if (eLightingMethod == VIS_LIGHTING_FULLBRIGHT)
            continue;
        }

        // If not all surfaces have a primary opaque pass type in the base pass, then render corresponding entity 
        // in the additive lighting pass.
        if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
        {
          iNumSurfaceShaders = 0;
          m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          break; 
        }

        // Check whether entity is in current shadow volume for orthographic shadows. In that case the entity is rendered
        // without shadows since it is not in the relevant shadow volume.
        IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
        if (pShadowMapGenDir)
        {
          if (!pShadowMapGenDir->IsEntityInsideOrthoShadowVolume(pEntity))
            pTmpShadowMapComponent = NULL;
        }
#endif

        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);
        if (!pTechnique || !pTechnique->GetShaderCount()) // do not light this surface
        {
          // If base-pass lighting technique could not be retrieved, render lit entity in the additive pass.
          if (bBasePass && pLight->IsDynamic())
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          iNumSurfaceShaders = 0;
          break; 
        }

        // Generate a list of surface shader from the combined surface/shader information
        VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
        info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
      }

      // Finally, render the entity with a surface shader list.
      if (iNumSurfaceShaders>0)
      {
        Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
        if (bBasePass)
          pEntity->Tag();
      }
    }

    Vision::RenderLoopHelper.EndEntityRendering();
  }

  // For all illuminated world primitives: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskWorld() != 0 && bStaticGeometry)
  {
    VisSurface_cl *pSurface;
    VisSurface_cl *pLastSurface = NULL;
    VCompiledTechnique *pLastTechnique = NULL;

    // We start collecting illuminated mesh instances. Whenever a relevant property changes, we set the
    // shader information, render all collected world instances, and start collecting from scratch.
    int iNumLitGeoInstances = pLitGeoInstanceCollection->GetNumEntries();
    pLastSurface = NULL;
    s_RenderGeoInstanceCollection.Clear();
    pLastTechnique = NULL;

    for (int j=0; j<iNumLitGeoInstances; j++)
    {
      VisStaticGeometryInstance_cl *pGI = pLitGeoInstanceCollection->GetEntry(j);

      pSurface = pGI->GetSurface();
      VASSERT(pSurface);
      if (pSurface->IsFullbright()) 
        continue; 

      // If surface does not have a primary opaque pass type in the base pass, then render corresponding static
      // mesh instance in the additive lighting pass.
      if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
      {
        m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue;
      }

      // Check whether mesh is in current shadow volume for orthographic shadows. In that case the mesh is rendered
      // without shadows since it is not in the relevant shadow volume.
      IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
      if (pShadowMapGenDir)
      {
        if (!pShadowMapGenDir->IsMeshInsideOrthoShadowVolume(pGI))
          pTmpShadowMapComponent = NULL;
      }
#endif

      if (pLastSurface!=pSurface)
      { 
        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);          
        pLastSurface = pSurface;
      }
      if (pTechnique == NULL || !pTechnique->GetShaderCount())
      {
        // If base-pass lighting technique could not be retrieved, render lit mesh in the additive pass.
        if (bBasePass && pLight->IsDynamic())
          m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue; 
      }

      // If the state information is different from the previous one, we have to render the world primitives we
      // have collected so far
      if (pLastTechnique!=pTechnique)
      {
        if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
        {
          VASSERT(pLastTechnique != NULL);
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
          if (bBasePass)
            s_RenderGeoInstanceCollection.TagEntries();
          s_RenderGeoInstanceCollection.Clear();      
        }
        // Update the stored state information
        pLastTechnique = pTechnique;
      }
      // Naturally, we have to append the primitive to our collection (otherwise it won't be collected =) ).
      s_RenderGeoInstanceCollection.AppendEntry(pGI);
    }

    // If there's still something left in the collection, render it as well.
    if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
    {
      if (pLastTechnique && pLastTechnique->GetShaderCount()>0)
      {
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
        if (bBasePass)
          s_RenderGeoInstanceCollection.TagEntries();
      } 
      s_RenderGeoInstanceCollection.Clear();
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}