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