void VTerrainDecorationEntityModel::RenderBatchDepthFill(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount)
{
  // depth fill rendering
  INSERT_PERF_MARKER_SCOPE("VTerrainDecorationEntityModel::RenderBatchDepthFill");

  VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  const int iNumSubmeshes = m_spMesh->GetSubmeshCount();
  int iAsmCount = 0;
  for (int i=0;i<iNumSubmeshes;i++)
  {
    VDynamicSubmesh *pSubmesh = m_spMesh->GetSubmesh(i);
    VisSurface_cl *pSurface = pSubmesh->GetSurface();
    if (pSurface->m_spDepthFill==NULL)
      continue;
    VisDrawCallInfo_t &assignment(surfaceShaderList[iAsmCount]);
    assignment.Set(pSubmesh, pSurface, pSurface->m_spDepthFill->GetShader(0));
    iAsmCount++;
  }
  Vision::RenderLoopHelper.BeginEntityRendering();
  for (int i=0;i<iCount;i++)
  {
    hkvMat4 transform(pInstList[i]->m_Orientation,pInstList[i]->m_vPosition);
    Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh, transform.getPointer (),iAsmCount,surfaceShaderList);
  }
  Vision::RenderLoopHelper.EndEntityRendering();
}
Beispiel #2
0
void VPostProcessFXAA::Execute()
{
  if (!IsActive() || !m_bIsInitialized)
    return;
 
  INSERT_PERF_MARKER_SCOPE("FXAA");

  RenderingOptimizationHelpers_cl::SetShaderPreference(112);

  if (m_spFrameCopyTexture != NULL)
  {
    Vision::Renderer.CopyToTexture(m_spFrameCopyTexture, 0, 0, m_iWidth, m_iHeight);
  }

  VCompiledShaderPass *pPass = m_spMask->GetTechnique()->GetShader(0);
  VShaderConstantBuffer *pPS = pPass->GetConstantBuffer(VSS_PixelShader);

  hkvVec4 invScreenSize(1.0f / m_iWidth, 1.0f / m_iHeight, 0, 0);

  if (m_iRegScreenSize >= 0)
  {
    pPS->SetSingleRegisterF(m_iRegScreenSize, invScreenSize.data);
  }

  tempMasks.Clear();
  tempMasks.AppendEntryFast(m_spMask);
  Vision::RenderLoopHelper.RenderScreenMasks(tempMasks);
}
void VSimpleCopyPostprocess::Execute()
{
  if (!IsActive() || !m_bIsInitialized)
    return;

  INSERT_PERF_MARKER_SCOPE("VSimpleCopyPostprocess");

  RenderingOptimizationHelpers_cl::SetShaderPreference(112);

  int iWidth, iHeight;
  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  pContext->GetSize(iWidth, iHeight);

  Vision::RenderLoopHelper.SetScissorRect(NULL);
  Vision::RenderLoopHelper.ClearScreen();

  // On DX9 a half pixel shift is required for the copy full screen pass.
#if defined(_VR_DX9)
  const hkvVec2 texelShift(1.0f / (float)(iWidth*2), 1.0f / (float)(iHeight*2));
#else
  const hkvVec2 texelShift(0.0f, 0.0f);
#endif

  VSimpleRenderState_t iState(VIS_TRANSP_NONE,RENDERSTATEFLAG_FRONTFACE|RENDERSTATEFLAG_ALWAYSVISIBLE|RENDERSTATEFLAG_NOWIREFRAME|RENDERSTATEFLAG_NOMULTISAMPLING);
  IVRender2DInterface *pRI = Vision::RenderLoopHelper.BeginOverlayRendering();
  pRI->DrawTexturedQuad(hkvVec2(0.f,0.f), hkvVec2((float)iWidth, (float)iHeight), m_spSourceTextures[0], hkvVec2(0.0f) + texelShift, hkvVec2(1.0f) + texelShift, V_RGBA_WHITE, iState);
  Vision::RenderLoopHelper.EndOverlayRendering();
}
void MirrorRenderLoop_cl::DrawStaticGeometry(const VisStaticGeometryInstanceCollection_cl &collection, int iPassType)
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::DrawStaticGeometry");

  m_CustomGeoInstances.Clear();

  int iNumGI = collection.GetNumEntries();
  VCompiledShaderPass *pCurrentPass = NULL;

  for (int i=0; i<iNumGI; i++)
  {
    VisStaticGeometryInstance_cl *pGI = collection.GetEntry(i);
    if ( pGI->GetGeometryType() == STATIC_GEOMETRY_TYPE_TERRAIN )
      ((VTerrainSector*)pGI)->EnsureLoaded();
    VCompiledShaderPass *pPass = GetMirrorShader (pGI->GetSurface (), m_pMirror->m_eReflectionShaderMode);
    if (pPass != pCurrentPass)
    {
      if (m_CustomGeoInstances.GetNumEntries() > 0)
      {
        VASSERT(pCurrentPass != NULL);
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pCurrentPass); // can use simplified lightmap shader
        m_CustomGeoInstances.Clear();
      }
      pCurrentPass = pPass;
    }
    m_CustomGeoInstances.AppendEntry(pGI);
  }

  // Render remaining instances
  if (m_CustomGeoInstances.GetNumEntries() > 0 && pCurrentPass != NULL)
    Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pCurrentPass); // can use simplified lightmap shader
}
void VBufferResolver::ResolveBuffer()
{
  INSERT_PERF_MARKER_SCOPE("VBufferResolver::ResolveBuffer");

  switch(m_eInitMode)
  {
    case VIM_CreateNewResolveBuffer:
      {
        VisRenderableTextureConfig_t pConfig = *m_spRenderContextToResolve->GetTargetConfig();

        if(pConfig.m_iWidth != m_iBufferWidth || pConfig.m_iHeight != m_iBufferHeight || pConfig.m_eFormat != m_eBufferFormat)
        {
          CreateResolveBuffer(NULL); // No override config needed, will use rendercontext config anyway
        }

        m_spRenderContextToResolve->ResolveToTexture(m_spResolvedBuffer, false);
      }
      break;

    case VIM_UseGivenResolveBuffer:
      {
        m_spRenderContextToResolve->ResolveToTexture(m_spResolvedBuffer, false);
      }
      break;

    default:
      VASSERT_MSG(0, "unhandled enum value");
  }
}
void VBlobShadowManager::OnHandleCallback(IVisCallbackDataObject_cl *pData)
{
    // hook into an existing renderloop to render the shadows (before rendering particles)
    if (pData->m_pSender==&Vision::Callbacks.OnRenderHook)
    {
        if (m_Instances.Count() && ((VisRenderHookDataObject_cl *)pData)->m_iEntryConst == m_iRenderHookConst)
        {
            INSERT_PERF_MARKER_SCOPE("Blob Shadow Rendering (VBlobShadowManager::OnHandleCallback)");
            RenderAllShadows();
        }
    }

    // UnloadWorld : do some per-scene deinitialisation
    else if (pData->m_pSender==&Vision::Callbacks.OnWorldDeInit)
    {
        ClearResources();
    }

    // Reassign shaders
    else if (pData->m_pSender == &Vision::Callbacks.OnReassignShaders)
    {
        // set shader resources to NULL, shaders will be recreated when
        // GetDefaultTechnique is called next time.
        m_spDefaultFX = NULL;
        m_spDefaultTech[0] = NULL;
        m_spDefaultTech[1] = NULL;
    }
}
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 VPostProcessScreenMasks::Execute()
{
  if (!IsActive() || !m_bIsInitialized)
    return;

  INSERT_PERF_MARKER_SCOPE("VPostProcessScreenMasks");

  RenderingOptimizationHelpers_cl::SetShaderPreference(112);
  
  VRendererNodeCommon::RenderOverlays(m_bRender2D, m_bRender3D);
}
void VMobileForwardRenderLoop::DrawDynamicLight()
{
  INSERT_PERF_MARKER_SCOPE("ForwardRenderer::DrawDynamicLight");

  unsigned int iNumLights = m_DynamicLightCollection.GetNumEntries();
  for (unsigned int i=0; i<iNumLights; i++)
  {
    VisLightSource_cl *pLight = m_DynamicLightCollection.GetEntry(i);
    bool bUsesLightClippingVolume = false;
    IVShadowMapComponent *pShadowMapComponent = PrepareLightingPass(pLight, false, bUsesLightClippingVolume);
    RenderLitGeometry(pLight, pShadowMapComponent, false, bUsesLightClippingVolume, true, true);
    FinalizeLightingPass(pLight, bUsesLightClippingVolume);
  }
}
void HmdRenderLoop::OnDoRenderLoop(void *pUserData)
{
  INSERT_PERF_MARKER_SCOPE("VCombine3DScreenRenderLoop::OnDoRenderLoop");

  Vision::RenderLoopHelper.ClearScreen();

  const float fWidth = float( Vision::Video.GetXRes() );
  const float fHeight = float( Vision::Video.GetYRes() );
  const hkvVec2 v2LeftEye1( 0.0f, 0.0f );
  const hkvVec2 v2LeftEye2( 0.5f * fWidth, fHeight );
  const hkvVec2 v2RightEye1( 0.5f * fWidth, 0.0f );
  const hkvVec2 v2RightEye2( fWidth, fHeight );
  const hkvVec2 v2UV0( 0.0f, 0.0f );
  const hkvVec2 v2UV1( 1.0f, 1.0f );

  IVRender2DInterface *pRI = Vision::RenderLoopHelper.BeginOverlayRendering();

  // Set common shader parameters.
  VShaderConstantBuffer* pConstantBuffer = m_spPostProcess[ m_eCurrentPostProcess ]->GetConstantBuffer( VSS_PixelShader );
  const ShaderRegisterSet& registerSet = m_shaderRegisters[ m_eCurrentPostProcess ];
  if ( registerSet.m_iScale_ScaleIn >= 0 )
    pConstantBuffer->SetSingleRegisterF( registerSet.m_iScale_ScaleIn, m_v4Scale_ScaleIn.data );
  if ( registerSet.m_iHmdWarpParameters >= 0)
    pConstantBuffer->SetSingleRegisterF( registerSet.m_iHmdWarpParameters, m_v4HmdWarpParameters.data );
  if ( registerSet.m_iChromaticAberration >= 0 )
    pConstantBuffer->SetSingleRegisterF( registerSet.m_iChromaticAberration, m_v4ChromaticAberration.data );

  // Set eye-specific shader parameters and render quads for the left and right eyes.
  if ( registerSet.m_iLensCenter_ScreenCenter >= 0 )
    pConstantBuffer->SetSingleRegisterF( registerSet.m_iLensCenter_ScreenCenter, m_v4LensCenter_ScreenCenter_LeftEye.data );
  pRI->DrawTexturedQuadWithShader( v2LeftEye1, v2LeftEye2, m_spSplitTexture[ 0 ], v2UV0, v2UV1, V_RGBA_WHITE, *m_spPostProcess[ m_eCurrentPostProcess ] );


  if ( registerSet.m_iLensCenter_ScreenCenter >= 0 )
    pConstantBuffer->SetSingleRegisterF( registerSet.m_iLensCenter_ScreenCenter, m_v4LensCenter_ScreenCenter_RightEye.data );
  pRI->DrawTexturedQuadWithShader( v2RightEye1, v2RightEye2, m_spSplitTexture[ 1 ], v2UV0, v2UV1, V_RGBA_WHITE, *m_spPostProcess[ m_eCurrentPostProcess ] );

  Vision::RenderLoopHelper.EndOverlayRendering();

  // Explicitly trigger message rendering.
  Vision::Message.HandleMessages();
}
bool VLightClippingVolumeRenderer::RenderLightClippingVolumeHelper(VisLightSource_cl *pLight,VStateGroupDepthStencil& sg)
{
  VLightClippingVolumeComponent* pComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
  if(pComponent != NULL && pComponent->GetVolume() != NULL && m_spLightClippingVolumeStencilFill)
  {
    INSERT_PERF_MARKER_SCOPE("VLightClippingVolumeRenderer::RenderLightClippingVolume");

    VisRenderStates_cl::SetDepthStencilState(sg);

    VCustomVolumeObject* pVolume = pComponent->GetVolume();

    VisStaticMesh_cl* pStaticMesh = pVolume->GetStaticMesh();
    if(!pStaticMesh)
      return false;

    VisMeshBuffer_cl* pMeshBuffer = pStaticMesh->GetMeshBuffer();
    if(!pMeshBuffer || pMeshBuffer->GetIndexCount() <= 0)
      return false;

    Vision::RenderLoopHelper.BeginMeshRendering();
    Vision::RenderLoopHelper.ResetMeshStreams();
    Vision::RenderLoopHelper.AddMeshStreams(pMeshBuffer, m_spLightClippingVolumeStencilFill->GetShader(0)->GetStreamMask() | VERTEX_STREAM_INDEXBUFFER);

    hkvMat4 transform;
    transform.setIdentity ();
    transform.setRotationalPart(pVolume->GetRotationMatrix());
    transform.setTranslation(pVolume->GetPosition());
    transform.setScalingFactors(pVolume->GetScale());

    Vision::RenderLoopHelper.SetMeshTransformationMatrix(transform);

    Vision::RenderLoopHelper.RenderMeshes(m_spLightClippingVolumeStencilFill->GetShader(0), pMeshBuffer->GetPrimitiveType(), 0, pMeshBuffer->GetIndexCount() / 3, pMeshBuffer->GetVertexCount());
    Vision::RenderLoopHelper.EndMeshRendering();

    return true;
  }
  return false;
}
void VPostProcessTranslucencies::MaskOutForegroundEntities(const VisEntityCollection_cl &EntityCollection)
{
  unsigned int iNumEntities = EntityCollection.GetNumEntries(); // this collection only contains foreground objects
  if (m_spForegroundMaskTechnique==NULL || iNumEntities==0)
    return;

  unsigned int i;
  const hkvMat4* pLastProj = NULL;
  INSERT_PERF_MARKER_SCOPE("VPostProcessTranslucencies::MaskOutForegroundEntities");

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0; i<iNumEntities; i++)
  {
    VisBaseEntity_cl *pEntity = EntityCollection.GetEntry(i);
    VASSERT_MSG(pEntity->IsObjectAlwaysInForegroundEnabled(), "Only entities with this flag should be passed to this function");
    if (!pEntity->HasShadersForPass(VPT_PrimaryOpaquePass))
      continue;

    const hkvMat4* pThisProj = pEntity->GetCustomProjectionMatrixForForegroundObject();
    if (pThisProj!=pLastProj)
    {
      VisRenderStates_cl::SetCurrentProjectionMatrix(pThisProj);
      pLastProj = pThisProj;
    }

    // depth fill pass
    Vision::RenderLoopHelper.RenderEntityWithShaders(pEntity, m_spForegroundMaskTechnique->GetShaderCount(), m_spForegroundMaskTechnique->GetShaderList());
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // reset to context projection matrix
  if (pLastProj)
  {
    VisRenderStates_cl::SetCurrentProjectionMatrix(NULL);
  }
}
// TODO: This doesn't handle opaque fullbright surfaces correctly yet, and translucent fullbright surfaces are simply ignored.
void MirrorRenderLoop_cl::OnDoRenderLoop(void *pUserData)
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::OnDoRenderLoop");

#if defined (WIN32) || defined (_VISION_XENON) || defined (_VISION_PS3) || defined(_VISION_PSP2) || defined(_VISION_WIIU)
  if (Vision::Editor.GetIgnoreAdvancedEffects())
  {
    // force a black reflection because it won't work with orthographic views
    Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, V_RGBA_BLACK);
    return;
  }
#endif

  VisRenderContext_cl *pContext = Vision::Contexts.GetCurrentContext();

  const int iRenderFlags = pContext->GetRenderFlags();

  const float fFarClipDist = m_pMirror->GetActualFarClipDistance();

  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);

  // set the oblique clipping plane...
  pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());

  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesPrimaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesSecondaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesTransparentPass;
  const VisEntityCollection_cl *pVisEntities;


  // === Visibility Determination ===

  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;
  const VisVisibilityObjectCollection_cl *pVisObjectCollection = pVisColl->GetVisibleVisObjects();

  hkvAlignedBBox box;
  int iVoCount = m_pMirror->GetVisibilityObjectCount();
  int iFrustumCount = 0;
  bool bUseCommonFrustum = false;

  // === Determine Scissor Rect ===
  hkvVec2 vMinScreenSpace, vMaxScreenSpace;
  const hkvAlignedBBox &worldSpaceBox = m_pMirror->GetBoundingBox();

  hkvVec3 vCorners[8];
  worldSpaceBox.getCorners (vCorners);

  VRectanglef scissorRect;
  bool bUseScissorRect = true;
  for (int i=0; i<8; i++)
  {
    float x2d, y2d;
    BOOL bInFrontOfCamera = pContext->Project2D(vCorners[i], x2d, y2d);
    if (bInFrontOfCamera)
    {
      scissorRect.Add(hkvVec2(x2d, y2d));
    }
    else
    {
      bUseScissorRect = false;
      break;
    }
  }

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(&scissorRect);

  for (int iVo = 0; iVo < iVoCount; iVo++)
  {
    VisVisibilityObject_cl *pVisObj = m_pMirror->GetVisibilityObject(iVo);
    if (pVisObj != NULL && pVisObj->WasVisibleInAnyLastFrame())
    {
      if (iFrustumCount <= MAX_SEPARATE_FRUSTA)
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        if (m_Frustum[iFrustumCount].Set(pContext->GetCamera()->GetPosition(), voBox, true, fFarClipDist))
        {
          iFrustumCount++;
        }
        else
        {
          bUseCommonFrustum = true;
        }
      }
      else
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        bUseCommonFrustum = true;
      }
    }
  }

  if (bUseCommonFrustum)
  {
    iFrustumCount = 1;
    if (!m_Frustum[0].Set(pContext->GetCamera()->GetPosition(), box, true, fFarClipDist))
      iFrustumCount = 0;
  }

  if (iFrustumCount>0)
  {
    for (int i=0; i<iFrustumCount; i++)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visEntities);
      if (iFrustumCount == 1)
        break;
      m_visiblePrimaryOpaquePassGeoInstances.TagEntries();
      m_visibleSecondaryOpaquePassGeoInstances.TagEntries();
      m_visibleTransparentOpaquePassGeoInstances.TagEntries();
      m_visEntities.TagEntries();
    }
    if (iFrustumCount > 1)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->GetTaggedEntries(m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->GetTaggedEntries(m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->GetTaggedEntries(m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->GetTaggedEntries(m_visEntities);
    }
    pVisibleGeoInstancesPrimaryOpaquePass = &m_visiblePrimaryOpaquePassGeoInstances;
    pVisibleGeoInstancesSecondaryOpaquePass = &m_visibleSecondaryOpaquePassGeoInstances;
    pVisibleGeoInstancesTransparentPass = &m_visibleTransparentOpaquePassGeoInstances;
    pVisEntities = &m_visEntities;
  }
  else
  {
    pVisibleGeoInstancesPrimaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);
    pVisibleGeoInstancesSecondaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass);
    pVisibleGeoInstancesTransparentPass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass);
    pVisEntities = pVisColl->GetVisibleEntities();
  }

  // === End Visibility Determination ===

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render opaque static geometry
  VASSERT(m_spDefaultLightMapping->m_Shaders.Count()==1);

  TRIGGER_MIRROR_HOOK(VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY)
  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;
  DrawStaticGeometry(*pVisibleGeoInstancesPrimaryOpaquePass, VPT_PrimaryOpaquePass);
  DrawStaticGeometry(*pVisibleGeoInstancesSecondaryOpaquePass, VPT_SecondaryOpaquePass);

  // Render entities
  const VisEntityCollection_cl *pEntities = pVisEntities;
  int iCount = pEntities->GetNumEntries();
  VASSERT(m_spDefaultLightGrid->m_Shaders.Count()==1);
  //VCompiledShaderPass *pLightgridShader = m_spDefaultLightGrid->m_Shaders.GetAt(0);
  int i;
  //bool bUseSimpleShader = shaderMode==VisMirror_cl::AlwaysSimple;

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0;i<iCount;i++)
  { 
    VisBaseEntity_cl *pEnt = pEntities->GetEntry(i);

//    Vision::RenderLoopHelper.TrackLightGridInfo(pEnt);  // important: need to be done in RenderEntityWithSurfaceShaderList

    //if (bUseSimpleShader)
    //{
    //  Vision::RenderLoopHelper.RenderEntityWithShaders(pEnt,1,&pLightgridShader);
    //}
    //else
    {
      VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACES];
      VDynamicMesh *pMesh = pEnt->GetMesh();
      VisSurface_cl **ppSurfaces = pEnt->GetSurfaceArray();
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      for (int j=0; j<iNumSubmeshes; j++)
      {
        VisDrawCallInfo_t &info(surfaceShaderList[j]);
        VBaseSubmesh* pSubmesh = pMesh->GetSubmesh(j);
        VisSurface_cl* pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];
        info.Set(pSubmesh, pSurface, GetMirrorShader (pSurface, shaderMode));
      }

      Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEnt, iNumSubmeshes, surfaceShaderList);
    }
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // Render Sky
  if (VSky::IsVisible())
  {
    // The sky has to be rendered without oblique clipping
    pContext->SetCustomProjectionMatrix(NULL);
    Vision::RenderLoopHelper.RenderSky();
    // set the oblique clipping plane after sky...
    pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());
  }

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_OCCLUSION_TESTS);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render Coronas / Lens Flares
  VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_CORONAS_AND_FLARES);
  Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  TRIGGER_MIRROR_HOOK(VRH_PRE_OCCLUSION_TESTS)  

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_OCCLUSIONQUERY)
    Vision::RenderLoopHelper.PerformHardwareOcclusionQuery();

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER)
    Vision::RenderLoopHelper.PerformHardwarePixelCounterQuery();

  DrawDynamicLight();

  TRIGGER_MIRROR_HOOK(VRH_DECALS)
  TRIGGER_MIRROR_HOOK(VRH_CORONAS_AND_FLARES)

  TRIGGER_MIRROR_HOOK(VRH_PRE_TRANSPARENT_PASS_GEOMETRY)
  DrawStaticGeometry(*pVisibleGeoInstancesTransparentPass, VPT_TransparentPass);
  TRIGGER_MIRROR_HOOK(VRH_POST_TRANSPARENT_PASS_GEOMETRY)

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(NULL);
}
// 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());
}
// Renders foreground entities (i.e. entities which have been flagged as "always in foreground")
void VPostProcessTranslucencies::DrawTransparentForegroundEntities(const VisEntityCollection_cl &EntityCollection)
{
  unsigned int iNumEntities = EntityCollection.GetNumEntries(); // this collection only contains foreground objects
  if (iNumEntities==0 || m_spForegroundFillPassTechnique==NULL)
    return;

  INSERT_PERF_MARKER_SCOPE("VisionRenderLoop_cl::DrawForegroundEntities");

  unsigned int i;
  const hkvMat4* pLastProj = NULL;

  Vision::RenderLoopHelper.BeginEntityRendering();
  const int iPassCount = m_spForegroundFillPassTechnique->GetShaderCount();
  for (int iPass=0;iPass<=iPassCount;iPass++) // +1 passes, where the last one is the actual material pass
  {
    for (i=0; i<iNumEntities; i++)
    {
      VisBaseEntity_cl *pEntity = EntityCollection.GetEntry(i);

      // Render only Entities that are flagged as "always in foreground"
      VASSERT_MSG(pEntity->IsObjectAlwaysInForegroundEnabled(), "Only entities with this flag should be passed to this function");

      if (pEntity->HasShadersForPass(VPT_TransparentPass))
      {
        VDynamicMesh *pMesh = pEntity->GetMesh();
        VisShaderSet_cl *pShaderSet = pEntity->GetActiveShaderSet();

        VASSERT(pMesh && pShaderSet);

        const hkvMat4* pThisProj = pEntity->GetCustomProjectionMatrixForForegroundObject();

        if (pThisProj != pLastProj)
        {
          VisRenderStates_cl::SetCurrentProjectionMatrix(pThisProj);
          pLastProj = pThisProj;
        }

        if (iPass<iPassCount) // depth fill pass
        {
          VCompiledShaderPass *pPass = m_spForegroundFillPassTechnique->GetShader(iPass);
          Vision::RenderLoopHelper.RenderEntityWithShaders(pEntity, 1, &pPass);
        }
        else // material pass
        {
          const VisDrawCallInfo_t *pAssignment;

          int iNumSurfaceShaders = pShaderSet->GetShaderAssignmentList(&pAssignment);

          // If the shaders make use of the lighting information, we need to track the light grid
          if (pMesh != NULL && pMesh->HasLitSurfaces() && 
            (pShaderSet->GetCombinedTrackingMask() & (VSHADER_TRACKING_LIGHTGRID_PS|VSHADER_TRACKING_LIGHTGRID_GS|VSHADER_TRACKING_LIGHTGRID_VS)) )
          {
            Vision::RenderLoopHelper.TrackLightGridInfo(pEntity);
          }

          // Render the entity with the surface shader list
          Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, pAssignment);
        }
      }
    }
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // reset to context projection matrix
  if (pLastProj)
  {
    VisRenderStates_cl::SetCurrentProjectionMatrix(NULL);
  }
}
void VTerrainDecorationEntityModel::RenderBatchDepthShadow(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount)
{
  // depth shader rendering
  INSERT_PERF_MARKER_SCOPE("VTerrainDecorationEntityModel::RenderBatchDepthShadow");
  VTerrainDecorationModelManager *pManager = (VTerrainDecorationModelManager *)GetParentManager();

  if (m_spInstancingTechShadow!=NULL && iCount>4 && pManager->m_iInstancingBatchCount>0 /* && bAllowInstancing*/)
  {
    VCompiledShaderPass *pShader = m_spInstancingTechShadow->GetShader(0);

    Vision::RenderLoopHelper.BeginMeshRendering();
    VisSurface_cl *pSurface = m_spMesh->GetSurface(0);
    Vision::RenderLoopHelper.BindSurfaceTextures(pSurface,pShader,NULL);
    Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface,pShader);
    VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType();
    int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount();
    int iVertexCount = m_spModelMesh->GetVertexCount();
    int iMaxInstanceCount, iInstanceStreamMask;
    VisMeshBuffer_cl *pInstanceMesh = ((VTerrainDecorationModelManager *)GetParentManager())->GetInstanceBuffer(iMaxInstanceCount,iInstanceStreamMask);

    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, m_iModelStreams);
    }
    Vision::RenderLoopHelper.EndMeshRendering();
  } 
  else
  {
    // non-instancing version
    VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
    const int iNumSubmeshes = m_spMesh->GetSubmeshCount();
    int iAsmCount = 0;
    for (int i=0;i<iNumSubmeshes;i++)
    {
      VDynamicSubmesh *pSubmesh = m_spMesh->GetSubmesh(i);
      VisDrawCallInfo_t &assignment(surfaceShaderList[iAsmCount]);
      if (pSubmesh->GetSurface()->m_spShadowmapFill==NULL)
        continue;
      assignment.Set(pSubmesh, pSubmesh->GetSurface(), pSubmesh->GetSurface()->m_spShadowmapFill->GetShader(0));
      iAsmCount++;
    }
    Vision::RenderLoopHelper.BeginEntityRendering();
    for (int i=0;i<iCount;i++)
    {
      hkvMat4 transform(pInstList[i]->m_Orientation,pInstList[i]->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh, transform.getPointer (),iAsmCount,surfaceShaderList);
    }
    Vision::RenderLoopHelper.EndEntityRendering();
  }
}
void VPostProcessTranslucencies::RenderParticles( const VisMeshBufferObjectCollection_cl * pVisibleMeshBuffer, const VisParticleGroupCollection_cl * pVisibleParticleGroups )
{
  if(!m_bQuarterSizeParticles)
  {
    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PARTICLES, true);
    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_ADDITIVE_PARTICLES, true); 
    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_TRANSLUCENT_VOLUMES, true);
  }
#if !defined(_VISION_MOBILE) && !defined(_VISION_PSP2)
  else
  {
    {
      // ALPHA-BLENDED PARTICLES + MESH BUFFERS
      INSERT_PERF_MARKER_SCOPE("VPostProcessTranslucencies: Alpha-Blended Particles (quarter-size)");

      SwitchToLowResContext();

      GetOwner()->RenderSceneDepth(true);
      Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_Color, VColorRef(0,0,0,255));

      RenderDeferredParticles(pVisibleParticleGroups, VRH_PARTICLES);
      VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, NULL, VRH_PARTICLES, true);


#if defined (_VISION_XENON)
      // Resolving is only required on Xbox360.
      m_spLowResColorTexture->Resolve();
#endif

      RestorePreviousContext();

      BlendQuarterSizeIntoTarget(m_spCopyTranslucenciesAlphaTechnique);
    }

    {
      // ADDITIVE PARTICLES + MESH BUFFERS
      INSERT_PERF_MARKER_SCOPE("VPostProcessTranslucencies: Additive Particles (quarter-size)");

      SwitchToLowResContext();

      Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_Color, VColorRef(0,0,0,0));

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


#if defined (_VISION_XENON)
      // Resolving is only required on Xbox360.
      m_spLowResColorTexture->Resolve();
#endif

      RestorePreviousContext();

      BlendQuarterSizeIntoTarget(m_spCopyTranslucenciesAdditiveTechnique);
    }

#ifdef _VISION_XENON
    //only a few pixels at the lower end of the depth buffer got overwritten
    //so we do a special depth restore only of the invalidated region of the depth buffer
    GetOwner()->RenderSceneDepthXbox360(VisHiZHelper_cl::VR_HIZ_RESTORE, -1.0f, -0.9f);
#endif

    //We can't trigger this render hook between VRH_PARTICLES and VRH_ADDITIVE_PARTICLES because of quarter size rendering
    VisionRenderLoop_cl::RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_TRANSLUCENT_VOLUMES, true);
  }
#endif
}
void VCoronaManager::RenderAllVisibleCoronas()
{
#ifdef SUPPORTS_CORONAS
  VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();

  // Determine relevant render context and visibility collector
  IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
  if (!pVisCollector)
    return;
  VisRenderContext_cl *pOQContext = pVisCollector->GetOcclusionQueryRenderContext();
  if (pOQContext != NULL)
    pContext = pOQContext;


  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER) == 0)
    return;

  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_RENDER_CORONAS) == 0)
    return;

  INSERT_PERF_MARKER_SCOPE("VCoronaManager::RenderAllVisibleCoronas");
  VISION_PROFILE_FUNCTION(PROFILING_CORONA_RENDER);

  // Force for the queries to finish so they are available in this frame.
  if (m_bTeleportedLastFrame && m_bForceQueryOnTeleport)
  {
    UpdateCoronas(VCUF_UPDATE | VCUF_FORCE_FETCH | VCUF_USE_OC_CONTEXT);
  }

  // Ensure size of corona state structure.
  int iContextIndex = pContext->GetNumber();
  if (iContextIndex + 1 > m_State.GetSize())
    m_State.SetSize(iContextIndex + 1, -1);
  VCoronaRenderContextState& state = m_State[iContextIndex];
  int iCapacity = m_Instances.GetCapacity();
  state.EnsureSize(iCapacity);

  const int iCoronasToRender = state.m_Candidates.GetSize();

  // Sort candidates by texture?
  
  VTextureObject* pTexture = NULL;

  // Render all corona components
  Vision::RenderLoopHelper.BeginMeshRendering();
  Vision::RenderLoopHelper.AddMeshStreams(m_spBillboardMesh,VERTEX_STREAM_POSITION);

  for (int i=0; i < iCoronasToRender; ++i)
  {
    VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i);
    if (coronaCandidate.m_fCurrentVisibility > 0.0f)
    {
      RenderCorona (coronaCandidate, pTexture);
    }
  }

  Vision::RenderLoopHelper.EndMeshRendering();

  m_bTeleportedLastFrame = (pContext->GetCamera()->GetLastTeleported() >= pContext->GetLastRenderedFrame());
#endif
}
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;
}
// renders visible wallmarks of specified pass type (pre or post, which is relevant in deferred context)
void VWallmarkManager::RenderProjectedWallmarks(VPassType_e ePassType)
{
  INSERT_PERF_MARKER_SCOPE("Wallmark Rendering (VWallmarkManager::RenderProjectedWallmarks)");

  const int iWallmarkCount = m_AllProjectedWallmarks.Count();
  IVisVisibilityCollector_cl *pVisCollector = Vision::Contexts.GetCurrentContext()->GetVisibilityCollector();
  if (!pVisCollector || !iWallmarkCount)
    return;

  const VisStaticGeometryInstanceCollection_cl *pGeoInstances = pVisCollector->GetVisibleStaticGeometryInstances();

  VisStaticGeometryInstance_cl::ResetTags();
  pGeoInstances->TagEntries();
  VisStaticGeometryInstanceCollection_cl &targetGiCollection = m_TempGeoInstanceCollection;

  VisRenderContext_cl *pContext = Vision::Contexts.GetCurrentContext();
  VisRenderContext_cl *pLODContext = pContext->GetLODReferenceContext();
  hkvVec3 vLODPos = pLODContext ? pLODContext->GetCamera()->GetPosition() : pContext->GetCamera()->GetPosition();

  unsigned int iContextFilter = pContext->GetRenderFilterMask();
  const VisFrustum_cl *pFrustum = pVisCollector->GetBaseFrustum();

  int i;
  for (i=0;i<iWallmarkCount;i++)
  {
    VProjectedWallmark *pProjWallmark = m_AllProjectedWallmarks.GetAt(i);
    if ((pProjWallmark->GetVisibleBitmask() & iContextFilter)==0 || (ePassType & pProjWallmark->m_ePassType) == 0)
      continue;
    pProjWallmark->PrepareForRendering();
    const VisStaticGeometryInstanceCollection_cl &wmGiList = pProjWallmark->GetStaticGeometryCollection();  

#ifdef HK_DEBUG
    const int iNum = wmGiList.GetNumEntries();
    for (int j=0;j<iNum;j++)
    {
      VisStaticGeometryInstance_cl *pInst = wmGiList.GetEntry(j);
      VASSERT_MSG(pInst && (pInst->GetGeometryType()==STATIC_GEOMETRY_TYPE_MESHINSTANCE || pInst->GetGeometryType()==STATIC_GEOMETRY_TYPE_TERRAIN), "The wallmark conains invalid primitive references")
    }
#endif

    // clip against its bounding box (primitive visibility might overestimate visible parts)
    const hkvAlignedBBox &bbox = pProjWallmark->GetBoundingBox();
    if (pProjWallmark->m_fFarClipDistance>0.f && pProjWallmark->m_fFarClipDistance<bbox.getDistanceTo(vLODPos))
      continue;
    if (pFrustum && !pFrustum->Overlaps(bbox))
      continue;

    const int iGeomFilter = pProjWallmark->GetGeometryTypeFilterMask();
    if (iGeomFilter&PROJECTOR_AFFECTS_STATICMESHES)
    {
      // standard geometry
      targetGiCollection.Clear();
      wmGiList.GetTaggedEntriesOfType(targetGiCollection,STATIC_GEOMETRY_TYPE_MESHINSTANCE);
      if (targetGiCollection.GetNumEntries())
      {
        // render the static geometry instances using lightmapped or non-lightmapped shader
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_MESHINSTANCE);
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(targetGiCollection, *pShader);
      }
    }

    if (iGeomFilter&PROJECTOR_AFFECTS_TERRAIN)
    {
      // terrain geometry (different shader)
      targetGiCollection.Clear();
      wmGiList.GetTaggedEntriesOfType(targetGiCollection,STATIC_GEOMETRY_TYPE_TERRAIN);
      if (targetGiCollection.GetNumEntries()>0)
      {
        // render the static geometry instances using lightmapped or non-lightmapped shader
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_TERRAIN);
        if (pShader)
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(targetGiCollection, *pShader);
      }
    }

    // entities
    if (iGeomFilter&PROJECTOR_AFFECTS_ENTITIES)
    {
      const VisEntityCollection_cl *pVisibleEntities = pVisCollector->GetVisibleEntities();
      const unsigned int iInfluenceMask = pProjWallmark->GetInfluenceBitmask();
      m_TempEntityCollection.Clear();
      const int iEntCount = pVisibleEntities->GetNumEntries();
      for (int j=0;j<iEntCount;j++)
      {
        VisBaseEntity_cl *pEntity = pVisibleEntities->GetEntry(j);
        if (pEntity==NULL || (pEntity->GetVisibleBitmask()&iInfluenceMask)==0)
          continue;
        const hkvAlignedBBox &entityBox(*pEntity->GetCurrentVisBoundingBoxPtr());
        if (!entityBox.overlaps(bbox))
          continue;
        m_TempEntityCollection.AppendEntry(pEntity);
      }
      if (m_TempEntityCollection.GetNumEntries()>0)
      {
        VProjectorShaderPass *pShader = GetWallmarkShader(pProjWallmark,STATIC_GEOMETRY_TYPE_MESHINSTANCE); // we can use this shader - VS skinning is used implicitly
        Vision::RenderLoopHelper.RenderEntitiesWithShader(m_TempEntityCollection, *pShader);
      }
    }

  }
}
Beispiel #21
0
//Update, render and display the scene
bool VisionApp_cl::Run()
{
  static bool bInsideGameLoop = false;

  // Make sure the game loop isn't executed recursively. In Windows builds, this could for example happen if a shown message box triggers
  // a repaint message. This case needs to be handled by the code calling the game loop.
  if(bInsideGameLoop)
  {
    // We can't report this error in a form that could trigger a message box, so reporting a warning and breaking the debugger is the best we can do.
    Vision::Error.Warning("VisionApp_cl::Run called recursively! This is usually caused by triggering a repaint from inside the game loop.");

#if defined(HK_DEBUG)
    VDBGBREAK;
#endif

    // Just skip the game loop - this may invoke weird behavior if the calling code expects the game loop to complete, but is better
    // than recursing
    return true;
  }

  bInsideGameLoop = true;

  //Update the scene
  m_iUpdateSceneTickCount = 1; // by default one simulation tick per loop
  if (m_spUpdateSceneController!=NULL)
    m_iUpdateSceneTickCount = m_spUpdateSceneController->GetUpdateTickCount();

  for (int i=0;i<m_iUpdateSceneTickCount;i++)
  {
    OnUpdateScene();
    if (i<m_iUpdateSceneTickCount-1) // the last one is performed after rendering
    {
      OnFinishScene();
      UpdateTimer();
    }
  }

  // update everything that has to be done once per loop rather than per simulation steps
  OnFrameUpdatePreRender();

  Vision::Profiling.Update();

  VASSERT_MSG(Vision::Renderer.GetRendererNode(0) != NULL, "No renderer node is set. This isn't supported anymore. Use a VSimpleRendererNode instead of registering the main context globally.");

  // If in debug build, perform a sanity check - no context registered with the main context should also be registered
  // with a renderer node!
#ifdef HK_DEBUG_SLOW
  static bool bContextErrorShown = false;
  if (!bContextErrorShown)
  {
    int iContextCount = Vision::Contexts.GetContextCount();
    for (int iContext = 0; iContext < iContextCount; iContext++)
    {
      for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++)
      {
        IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode);
        VisRenderContext_cl* pContext = Vision::Contexts.GetContext(iContext);
        if (pNode != NULL && pNode->IsContextRegistered(Vision::Contexts.GetContext(iContext)))
        {
          Vision::Error.Warning("Context %s (%p) is registered globally AND in renderer node %s (%p). This may be intended, but it is most likely a porting issue introduced by porting from a pre-8.0 version of the Vision Engine.",
            pContext->GetName(), pContext, pNode->GetTypeId()->m_lpszClassName, pNode);
          bContextErrorShown = true;
        }
      }
    }
  }
#endif

  {
    INSERT_PERF_MARKER_SCOPE("BeginRendering");

    // Inform the renderer that we are now going to start rendering
    Vision::Renderer.BeginRendering();
    Vision::Callbacks.BeginRendering.TriggerCallbacks();
  }


  Vision::Renderer.SetCurrentRendererNode(NULL);
  VisRendererNodeDataObject_cl data(&Vision::Callbacks.OnRendererNodeSwitching, NULL);
  Vision::Callbacks.OnRendererNodeSwitching.TriggerCallbacks(&data);


  {
    INSERT_PERF_MARKER_SCOPE("PreRendererNodeContexts");
    Vision::Contexts.PerformVisibilityTests();
    Vision::Contexts.RenderContexts(-FLT_MAX, VIS_RENDERCONTEXTPRIORITY_SCENE);
  }

  {
    for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++)
    {
      IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode);

      if (pNode != NULL && pNode->GetRenderingEnabled())
      {
        char buffer[192];
        sprintf(buffer, "RendererNode %d (%s)", iRendererNode, pNode->GetTypeId()->m_lpszClassName);
        INSERT_PERF_MARKER_SCOPE(buffer);

        VASSERT_MSG(pNode->IsInitialized(), "Renderer Node is registered and enabled, but not initialized");
        pNode->Execute();
      }
    }
  }

  {
    INSERT_PERF_MARKER_SCOPE("PostRendererNodeContexts");
    Vision::Renderer.SetCurrentRendererNode(NULL);
    Vision::Contexts.RenderContexts(VIS_RENDERCONTEXTPRIORITY_SCENE, FLT_MAX);
  }

  {
    INSERT_PERF_MARKER_SCOPE("EndRendering");

    // Tell the renderer that we have finished rendering
    Vision::Callbacks.EndRendering.TriggerCallbacks();
    Vision::Renderer.EndRendering();
  }

  //Finish the scene - the last tick is performed here
  if (m_iUpdateSceneTickCount>0)
    OnFinishScene();

  // update everything that has to be done once per loop rather than per simulation steps
  OnFrameUpdatePostRender();

  //Display the scene
  Vision::Callbacks.OnBeforeSwapBuffers.TriggerCallbacks();
#ifdef WIN32
  if (m_bUpdateScreen) // only supported on win32
#endif
    Vision::Video.UpdateScreen();

  if (m_iUpdateSceneTickCount>0) // same as for OnFinishScene
    UpdateTimer();

  bInsideGameLoop = false;

  return !WantsToQuit();
}