// ----------------------------------------------------------------------------
void vHavokChainConstraintChainRenderer::DrawEntity(VPassType_e ePassType)
{
  // Code copied from VisionRenderLoop_cl::DrawEntitiesShaders()

  if (!m_spChainEntity->HasShadersForPass(ePassType))
    return;

  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];

  // Get a list of the corresponding pass type shader set
  VisShaderSet_cl *pShaderSet = m_spChainEntity->GetActiveShaderSet();
  if (pShaderSet == NULL)
    return;

  int iNumSurfaceShaders = pShaderSet->GetShaderAssignmentList(SurfaceShaderList, ePassType, RLP_MAX_ENTITY_SURFACESHADERS);
  VASSERT(iNumSurfaceShaders < RLP_MAX_ENTITY_SURFACESHADERS);
  if (iNumSurfaceShaders == 0)
    return;

  // If the model has lit surfaces, and if the shaders makes use of the lighting information, we need to set up
  // the global lights.
  if (m_spChainMesh->HasLitSurfaces())
  {
    if(pShaderSet->GetCombinedTrackingMask() & (VSHADER_TRACKING_LIGHTGRID_PS|VSHADER_TRACKING_LIGHTGRID_GS|VSHADER_TRACKING_LIGHTGRID_VS))
    {
      Vision::RenderLoopHelper.TrackLightGridInfo(m_spChainEntity);
    }
  }

  // Render the entity with the surface shader list
  Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(m_spChainEntity, iNumSurfaceShaders, SurfaceShaderList);
}
// Render shaders on entities
void VPostProcessTranslucencies::DrawEntitiesShaders(const VisEntityCollection_cl &EntityCollection, VPassType_e ePassType)
{
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  unsigned int iNumEntities = EntityCollection.GetNumEntries();
  unsigned int i;

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0; i<iNumEntities; i++)
  {
    VisBaseEntity_cl *pEntity = EntityCollection.GetEntry(i);
    // Foreground entities will be handled separately
    if (pEntity->IsObjectAlwaysInForegroundEnabled()) continue;
    if ( pEntity->HasShadersForPass(ePassType) )
    {
      // Get a list of the corresponding pass type surface shaders
      VisShaderSet_cl *pShaderSet = pEntity->GetActiveShaderSet();
      if (pShaderSet == NULL) continue;
      int iNumSurfaceShaders = pShaderSet->GetShaderAssignmentList(SurfaceShaderList, ePassType, RLP_MAX_ENTITY_SURFACESHADERS);
      VASSERT(iNumSurfaceShaders < RLP_MAX_ENTITY_SURFACESHADERS);
      if (iNumSurfaceShaders == 0) continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();

      // If the model has lit surfaces, and if the shaders makes use of the lighting information, we need to set up
      // the global lights.
      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, SurfaceShaderList);
    } 
  }

  Vision::RenderLoopHelper.EndEntityRendering();

} 
void VTerrainDecorationEntityModel::RenderBatchOTW(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount)
{
  // OTW rendering
  VTerrainDecorationModelManager *pManager = (VTerrainDecorationModelManager *)GetParentManager();
  if (m_spInstancingTech!=NULL && iCount>4 && pManager->m_iInstancingBatchCount>0 /* && bAllowInstancing*/)
  {
    VCompiledShaderPass *pShader = m_spInstancingTech->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);

    // lightmap version
    if (m_iLightmapSampler>=0 && pInfoComp!=NULL)
    {
#ifdef HK_DEBUG
      const VStateGroupTexture *pStateGroupTexture = pShader->GetStateGroupTexture(VSS_PixelShader, m_iLightmapSampler);
      VASSERT(pStateGroupTexture!=NULL && pStateGroupTexture->m_cTextureType==TEXTURETYPE_LIGHTMAP);
#endif

      VStateGroupSampler *pLMSampler = pShader->GetStateGroupSampler(VSS_PixelShader, m_iLightmapSampler);
      VTerrainSector *pLastSector = NULL;
      VTextureObject *pTerrainLightmap = NULL;
      const VTerrainConfig& config(pInfoComp->m_pTerrain->m_Config);
      VTerrainSectorManager &sectormanager(pInfoComp->m_pTerrain->m_SectorManager);
      while (iCount>0)
      {
        int iWantedRenderCount = hkvMath::Min(iCount,iMaxInstanceCount);
        int iRenderCount = 0;

        // fill the instance buffer:
        {
          VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);
          VModelInstanceData_t *pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE,0,iWantedRenderCount);
          // fill buffer up to lightmap change
          for (int i=0;i<iWantedRenderCount;i++,iRenderCount++,pDest++)
          {
            if (pLastSector!=pInstList[i]->m_pOwnerSector)
            {
              pLastSector = pInstList[i]->m_pOwnerSector;
              VTextureObject *pNewLightmap = pLastSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0];
              if (pNewLightmap!=pTerrainLightmap)
              {
                if (iRenderCount>0) // start a new batch so break here
                  break;
              }
            }
            pDest->Set(*pInstList[i]);
          }
          pInstanceMesh->UnLockVertices();
        }

        // bind sector specific properties
        VTerrainSector *pStateSetupSector = pInstList[0]->m_pOwnerSector; // this is where the batch starts
        hkvVec4 vWorld2Sector(false);
        // transforms worldspace to sector 0..1 range
        config.GetWorldSpaceToSectorTransform(pStateSetupSector->m_iIndexX,pStateSetupSector->m_iIndexY,vWorld2Sector);
        sectormanager.SetWorld2SectorTransform(vWorld2Sector);
          // standard range -> lightmap
        const hkvVec4 vSector2LM = pStateSetupSector->GetLightmapScaleOffset();
        VisRenderStates_cl::VSSetModelUVToLightmap(vSector2LM.data);
        Vision::RenderLoopHelper.BindMeshTexture(pStateSetupSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0],m_iLightmapSampler,pLMSampler);

        // advance by actual render counts
        pInstList += iRenderCount;
        iCount-=iRenderCount;
        RENDER_INSTANCES(iRenderCount, m_iModelStreams);
      }

    }
    else // non-lightmapped version
    {
      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();
    return;
  }

  //////////////////////////////////////////////////////////
  // Non-instancing  version

  const VisDrawCallInfo_t *pSurfaceShaderList;
  VDynamicMesh *pMesh = m_spMesh;
  VASSERT(m_spVegetationShaders!=NULL);
  VisShaderSet_cl *pSet = m_spVegetationShaders;
  int iAsmCount = pSet->GetShaderAssignmentList(&pSurfaceShaderList);
  VColorRef iLastColor;

  #ifdef _VR_DX11
    VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
  #endif

  if (m_bNeedsLightmap && pInfoComp!=NULL)
  {
    VTerrainSector *pLastSector = NULL;
    VTextureObject *pTerrainLightmap = NULL;
    const VTerrainConfig& config(pInfoComp->m_pTerrain->m_Config);
    VTerrainSectorManager &sectormanager(pInfoComp->m_pTerrain->m_SectorManager);

    Vision::RenderLoopHelper.BeginEntityRendering();
    for (int i=0;i<iCount;i++,pInstList++)
    {
      if (pLastSector!=(*pInstList)->m_pOwnerSector)
      {
        pLastSector = (*pInstList)->m_pOwnerSector;
        VTextureObject *pNewLightmap = pLastSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0];
        if (pNewLightmap!=pTerrainLightmap)
        {
          // assign new model lightmaps
          const int iSrfCount = m_spMesh->GetSurfaceCount();
          for (int j=0;j<iSrfCount;j++)
            m_spMesh->GetSurface(j)->m_spModelLightmaps[0] = pNewLightmap;

          // and also force a shader re-binding
          for (int j=0;j<iAsmCount;j++)
            pSurfaceShaderList[j].GetShader()->m_bModified=true;

          pTerrainLightmap = pNewLightmap;
        }

        hkvVec4 vWorld2Sector(false);
        // transforms worldspace to sector 0..1 range
        config.GetWorldSpaceToSectorTransform(pLastSector->m_iIndexX,pLastSector->m_iIndexY,vWorld2Sector);
        sectormanager.SetWorld2SectorTransform(vWorld2Sector);
          // standard range -> lightmap
        const hkvVec4 vSector2LM = pLastSector->GetLightmapScaleOffset();
        VisRenderStates_cl::VSSetModelUVToLightmap(vSector2LM.data);
      }

      // per instance tint color
      if (i==0 || iLastColor!=(*pInstList)->m_InstanceColor)
      {
        iLastColor = (*pInstList)->m_InstanceColor;
        VPerInstanceData_t &data(m_PerInstanceData.BeginUpdate());
          VColorRef::RGBA_To_Float((*pInstList)->m_InstanceColor, data.vPerInstanceColor);
        m_PerInstanceData.EndUpdate();
      #ifndef _VR_DX11
        VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
      #endif
      }

      // finally render object
      hkvMat4 transform((*pInstList)->m_Orientation,(*pInstList)->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh,transform.getPointer (),iAsmCount,pSurfaceShaderList);
    }
    VisRenderStates_cl::SetVSConstantBuffer(7,NULL);
    Vision::RenderLoopHelper.EndEntityRendering();
  }
  else
  {
    Vision::RenderLoopHelper.BeginEntityRendering();

    // no lightmaps -> simple loop 
    for (int i=0;i<iCount;i++,pInstList++)
    {
      // per instance tint color
      if (i==0 || iLastColor!=(*pInstList)->m_InstanceColor)
      {
        iLastColor = (*pInstList)->m_InstanceColor;
        VPerInstanceData_t &data(m_PerInstanceData.BeginUpdate());
          VColorRef::RGBA_To_Float((*pInstList)->m_InstanceColor, data.vPerInstanceColor);
        m_PerInstanceData.EndUpdate();
      #ifndef _VR_DX11
        VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
      #endif
      }
      hkvMat4 transform((*pInstList)->m_Orientation,(*pInstList)->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh,transform.getPointer(),iAsmCount,pSurfaceShaderList);
    }

    VisRenderStates_cl::SetVSConstantBuffer(7,NULL);

    Vision::RenderLoopHelper.EndEntityRendering();
  }
}
// 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);
  }
}