void VPostProcessTranslucencies::Execute()
{
  INSERT_PERF_MARKER_SCOPE("VPostProcessTranslucencies");

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
  VASSERT(pVisCollector != NULL);

  const VisEntityCollection_cl *pVisibleForeGroundEntities = pVisCollector->GetVisibleForeGroundEntities();

  m_VisibilityObjectCollector.HandleVisibleVisibilityObjects();

#ifndef _VISION_MOBILE
  RenderingOptimizationHelpers_cl::SetShaderPreference(96);
#endif

  // Get a pointer to the collection of visible mesh buffer objects
  const VisMeshBufferObjectCollection_cl *pVisibleMeshBuffer = &m_VisibilityObjectCollector.GetMeshBufferObjectCollection();

  // Get a pointer to the collection of visible particle groups
  const VisParticleGroupCollection_cl *pVisibleParticleGroups = &m_VisibilityObjectCollector.GetParticleGroupCollection();

  // Mask out entities which are "always in foreground"
  MaskOutForegroundEntities(*pVisibleForeGroundEntities);

  if (pVisCollector->GetInterleavedTranslucencySorter() == NULL)
  {
    // --- Traditional transparency sorting (default)
    const VisStaticGeometryInstanceCollection_cl *pVisibleTransparentGeoInstances = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass);
    const VisEntityCollection_cl *pVisibleEntities = pVisCollector->GetVisibleEntitiesForPass(VPT_TransparentPass);

    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_GEOMETRY, true);

    // render transparent pass surface shaders on translucent static geometry instances
    Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleTransparentGeoInstances, VPT_TransparentPass);

    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_ENTITIES, true);

    // Render transparent pass shaders on entities
    DrawEntitiesShaders(*pVisibleEntities, VPT_TransparentPass);

    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_POST_TRANSPARENT_PASS_GEOMETRY, true);

    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_DECALS, true);

    RenderParticles(pVisibleMeshBuffer, pVisibleParticleGroups);
  }
  else
  {
    // --- Interleaved transparency sorting
    pVisCollector->GetInterleavedTranslucencySorter()->OnRender(pVisCollector, true);
  }

  // Render visible foreground entities (see DrawForegroundEntities)
  DrawTransparentForegroundEntities(*pVisibleForeGroundEntities);

  // Coronas and flares will be still rendered after the other interleaved sorted objects were rendered (lensflare and coronas don't must be always rendered "on top") 
  VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_CORONAS_AND_FLARES, true);
}
void VMobileForwardRenderLoop::OnDoRenderLoop(void *pUserData)
{
  INSERT_PERF_MARKER_SCOPE("VMobileForwardRenderLoop::OnDoRenderLoop");

  m_iFrameCounter++; // just for arbitrary custom purposes

#ifdef WIN32
  // vForge specific:
  if (Vision::RenderLoopHelper.GetReplacementRenderLoop())
  {
    // render with this render-loop instead
    Vision::RenderLoopHelper.GetReplacementRenderLoop()->OnDoRenderLoop(pUserData);
    return;
  }
#endif

  m_pShaderProvider = Vision::GetApplication()->GetShaderProvider();
  VASSERT(m_pShaderProvider);
  m_pShaderProvider->ResetCache();

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
  if (pVisCollector==NULL)
    return; 

  const int iRenderFlags = pContext->GetRenderFlags();
  m_pCameraFrustum = pVisCollector->GetBaseFrustum(); 

  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesPrimaryOpaquePass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesSecondaryOpaquePass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass);
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesTransparentPass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass);
  const VisEntityCollection_cl *pVisibleEntitiesPrimaryOpaquePass = pVisCollector->GetVisibleEntitiesForPass(VPT_PrimaryOpaquePass);
  const VisEntityCollection_cl *pVisibleEntitiesSecondaryOpaquePass = pVisCollector->GetVisibleEntitiesForPass(VPT_SecondaryOpaquePass);
  const VisEntityCollection_cl *pVisibleEntitiesTransparentPass = pVisCollector->GetVisibleEntitiesForPass(VPT_TransparentPass);
  const VisEntityCollection_cl *pVisibleForeGroundEntities = pVisCollector->GetVisibleForeGroundEntities();
  HandleVisibleVisibilityObjects();

  // Clear the screen
  if ((iRenderFlags&VIS_RENDERCONTEXT_FLAG_NO_CLEARSCREEN)==0)
  {
    const VFogParameters &fog = Vision::World.GetFogParameters();
    VColorRef clearColor = fog.depthMode != VFogParameters::Off ? fog.iDepthColor : Vision::Renderer.GetDefaultClearColor();
    Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, clearColor);
  }

  m_bHasRenderHookCallbacks = m_bTriggerCallbacks && Vision::Callbacks.OnRenderHook.HasCallbacks();

  // Get a pointer to the collection of visible mesh buffer objects
  const VisMeshBufferObjectCollection_cl *pVisibleMeshBuffer = &m_VisibilityObjectCollector.GetMeshBufferObjectCollection();

  // Get a pointer to the collection of visible particle groups
  const VisParticleGroupCollection_cl *pVisibleParticleGroups = &m_VisibilityObjectCollector.GetParticleGroupCollection();

  // Determine which lights have to rendered in the current frame
  DetermineRelevantLights();

  // Render all mesh buffer objects with the render order flag "VRH_PRE_RENDERING".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_RENDERING, m_bTriggerCallbacks);

  // Render all mesh buffer objects with the render order flag "VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY, m_bTriggerCallbacks);

  // Reset tags
  VisStaticGeometryInstance_cl::ResetTags();
  VisBaseEntity_cl::ResetTags();
  
  // Clear temporary collections for geometry that is lit by base pass light, but rendered in additive lighting pass
  m_AdditiveLitGeoInstanceCollection.Clear();
  m_AdditiveLitEntityCollection.Clear();

  // Prepare the initial lighting pass (one light collapsed with base lighting contribution)
  bool bUsesLightClippingVolume = false;
  IVShadowMapComponent *pShadowMap = PrepareLightingPass(m_pBasePassLight, true, bUsesLightClippingVolume);

  // Render lit geometry before actual base pass, whereby the geometry which has been rendered here will be tagged, in order
  // to avoid re-rendering later on. We first render static meshes lit base the base pass light, then static meshes not lit by the base pass light,
  // and then entities (with/without base pass light, respectively).
  {
    RenderLitGeometry(m_pBasePassLight, pShadowMap, true, bUsesLightClippingVolume, false, true);

    // Render all primary opaque pass surface shaders on opaque world geometry
    Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesPrimaryOpaquePass, VPT_PrimaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES); 

    // Render all mesh buffer objects with the render order flag "VRH_PRE_PRIMARY_OPAQUE_PASS_ENTITIES".
    RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_PRIMARY_OPAQUE_PASS_ENTITIES, m_bTriggerCallbacks);

    RenderLitGeometry(m_pBasePassLight, pShadowMap, true, bUsesLightClippingVolume, true, false);

    // Render all primary opaque pass shaders on entities (see "DrawEntitiesShaders")
    DrawEntitiesShaders(*pVisibleEntitiesPrimaryOpaquePass, VPT_PrimaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES);
  }

  // Finalize the initial pass
  FinalizeLightingPass(m_pBasePassLight, bUsesLightClippingVolume);

  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_SECONDARY_OPAQUE_PASS_GEOMETRY, m_bTriggerCallbacks);

  // Render static geometry instances for secondary opaque pass
  Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesSecondaryOpaquePass, VPT_SecondaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES);
  
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_SECONDARY_OPAQUE_PASS_ENTITIES, m_bTriggerCallbacks);

  // Render entities for secondary opaque pass
  DrawEntitiesShaders(*pVisibleEntitiesSecondaryOpaquePass, VPT_SecondaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES);

  // Start the hardware occlusion query. Note that this function always has to be called in render loops.
  // Also, the position of this call in the OnDoRenderLoop is important: The zBuffer contents at this stage of rendering will
  // act as occluders in the hardware occlusion queries.
  Vision::RenderLoopHelper.PerformHardwareOcclusionQuery();

  // Render sky
  Vision::RenderLoopHelper.RenderSky();

  // Render all mesh buffer objects with the render order flag "VRH_PRE_OCCLUSION_TESTS".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_OCCLUSION_TESTS, m_bTriggerCallbacks);

  Vision::RenderLoopHelper.PerformHardwarePixelCounterQuery();

  // Render all mesh buffer objects with the render order flag "VRH_POST_OCCLUSION_TESTS".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_POST_OCCLUSION_TESTS, m_bTriggerCallbacks);

  // Draw dynamic light 
  DrawDynamicLight();

  // Render all mesh buffer objects with the render order flag "VRH_PRE_TRANSPARENT_PASS_GEOMETRY".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_GEOMETRY, m_bTriggerCallbacks); 
  
  // Render transparent pass surface shaders on translucent lit world primitives
  Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesTransparentPass, VPT_TransparentPass, VTF_IGNORE_TAGGED_ENTRIES);

  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_ENTITIES, m_bTriggerCallbacks);

  // Render transparent pass shaders on entities
  DrawEntitiesShaders(*pVisibleEntitiesTransparentPass, VPT_TransparentPass, VTF_IGNORE_TAGGED_ENTRIES);

  // Render all mesh buffer objects with the render order flag "VRH_POST_TRANSPARENT_PASS_GEOMETRY".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_POST_TRANSPARENT_PASS_GEOMETRY, m_bTriggerCallbacks);

  // Render all mesh buffer objects and particle systems with the render order flag "VRH_DECALS".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_DECALS, m_bTriggerCallbacks);

  // Render all mesh buffer objects and particle systems with the render order flag "VRH_PARTICLES".
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PARTICLES, m_bTriggerCallbacks);

  // Render all mesh buffer objects with the render order flag "VRH_ADDITIVE_PARTICLES"
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_ADDITIVE_PARTICLES, m_bTriggerCallbacks);

  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_TRANSLUCENT_VOLUMES, m_bTriggerCallbacks);

  // Render visible foreground entities (see DrawForegroundEntities)
  DrawForegroundEntities(*pVisibleForeGroundEntities);

  // Render all mesh buffer objects with the render order flag "VRH_CORONAS_AND_FLARES"
  RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_CORONAS_AND_FLARES, m_bTriggerCallbacks);

  m_pShaderProvider = NULL;
}