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); } }
// 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(); }
// 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); } }