void VRendererNodeCommon::DrawMeshBufferObjects(unsigned int iRenderOrder) { s_MeshBufferObjectCollection.Clear(); VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext(); int iRenderFlags = pContext->GetRenderFilterMask(); int iNumMeshBufferObjects = VisMeshBufferObject_cl::ElementManagerGetSize(); for (int i=0;i<iNumMeshBufferObjects;i++) { VisMeshBufferObject_cl *pMeshBufferObject = VisMeshBufferObject_cl::ElementManagerGet(i); if (!pMeshBufferObject) continue; if (!(pMeshBufferObject->GetVisibleBitmask() & iRenderFlags)) continue; if (pMeshBufferObject->GetOrder() != iRenderOrder) continue; s_MeshBufferObjectCollection.AppendEntry(pMeshBufferObject); } Vision::RenderLoopHelper.RenderMeshBufferObjects(s_MeshBufferObjectCollection, iRenderOrder); }
// 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); } } } }
void VCoronaManager::UpdateCoronas(int iCoronaUpdateFlags) { #ifdef SUPPORTS_CORONAS VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext(); if ((iCoronaUpdateFlags & VCUF_USE_OC_CONTEXT) > 0) { // 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 == NULL) return; if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER) == 0) return; if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_RENDER_CORONAS) == 0) return; // Get bitmask for this context. unsigned int iRenderFilterMask = pContext->GetRenderFilterMask(); // get the collection of visible lights. IVisVisibilityCollector_cl* pVisCollector = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector(); if (pVisCollector == NULL) return; VISION_PROFILE_FUNCTION(PROFILING_CORONA_UPDATE); // Get multi-sampling mode unsigned int iTexelsPerPixel = 1; VTextureObject* pDepthTex = pContext->GetDepthStencilTarget(); if(pDepthTex == NULL) { // If no depth stencil target is available, we might work without a renderer node and we're in the main context if(Vision::Renderer.GetCurrentRendererNode() == NULL && pContext == VisRenderContext_cl::GetMainRenderContext()) { // In this case get the multi-sampling type from the video config as it's used to set the actual backbuffer settings // where the main context will render to iTexelsPerPixel = hkvMath::Max(1, 1 << ((int)Vision::Video.GetCurrentConfig()->m_eMultiSample)); } } else if (pDepthTex->GetTextureType() == VTextureLoader::Texture2D) { iTexelsPerPixel = hkvMath::Max(1u, ((VisRenderableTexture_cl*)pDepthTex)->GetConfig()->m_iMultiSampling); } const VisLightSrcCollection_cl* pVisibleLights = pVisCollector->GetVisibleLights(); int iCandidates = 0; if (pVisibleLights != NULL) iCandidates = pVisibleLights->GetNumEntries(); // Ensure size of coronas 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); // Add visible lights with a lens flare component to the candidate list for this frame if ((iCoronaUpdateFlags & VCUF_ADD) > 0) { for (int iCandidate = 0; iCandidate < iCandidates; ++iCandidate) { VisLightSource_cl* pLight = pVisibleLights->GetEntry(iCandidate); if (pLight) { VCoronaComponent *pComponent = pLight->Components().GetComponentOfBaseType<VCoronaComponent>(); if (pComponent != NULL && pComponent->IsEnabled() && !state.IsBitSet(pComponent->m_iIndex)) { // The component is not in m_Candidates yet, so we check whether it is a valid candidate bool bIsLightOnScreen = pComponent->IsValidCandidate(pContext); if (bIsLightOnScreen) { state.SetBit(pComponent->m_iIndex); pContext->SetPixelCounterResult(pComponent->m_CoronaPixelCounter.GetNumber(), 0); state.m_Candidates.Append(pComponent); } } } } } // Forces the retrieval all pending queries. pContext->FetchPixelCounterTestResults( (iCoronaUpdateFlags & VCUF_FORCE_FETCH) > 0 ); // Retrieve Queries and update status of lens flares if ((iCoronaUpdateFlags & VCUF_UPDATE) > 0) { for (int i=0; i < state.m_Candidates.GetSize(); ++i) { VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i); VCoronaComponent* pCorona = coronaCandidate.m_pCorona; if (!pCorona || !pCorona->IsEnabled()) continue; if (pCorona->GetOwner()) { // Retrieve occlusion results of the last query unsigned int iElementIndex = pCorona->m_CoronaPixelCounter.GetNumber(); bool bRes = !pContext->IsPixelCounterQueryInProgress(iElementIndex); // Reschedule query if the old on could be retrieved or if a teleport forces us to re-query everything. if (bRes | ((iCoronaUpdateFlags & VCUF_FORCE_SCHEDULE) > 0) ) pContext->SchedulePixelCounterTest(iElementIndex); unsigned int iDrawnPixels = pContext->GetPixelCounterResult(iElementIndex) / iTexelsPerPixel; float fVisibility = (float)iDrawnPixels / ((int)pCorona->QueryRadius * (int)pCorona->QueryRadius * 4); // ATI fix for random insanely high return values. if (iDrawnPixels > ((unsigned int)pCorona->QueryRadius * 2 + 1) * ((unsigned int)pCorona->QueryRadius * 2 + 1)) { fVisibility = coronaCandidate.m_fLastVisibilityQuery; } if ((iCoronaUpdateFlags & VCUF_FORCE_FETCH) > 0) { // Force lens flare visibility to the current query value. coronaCandidate.m_fCurrentVisibility = fVisibility; coronaCandidate.m_fLastVisibilityQuery = fVisibility; pCorona->UpdateVisibility(coronaCandidate.m_fLastVisibilityQuery, coronaCandidate.m_fCurrentVisibility); } else if (!m_bTeleportedLastFrame) { coronaCandidate.m_fLastVisibilityQuery = fVisibility; pCorona->UpdateVisibility(coronaCandidate.m_fLastVisibilityQuery, coronaCandidate.m_fCurrentVisibility); } else { // if we were teleported, the last frame's query results must be invalidated coronaCandidate.m_fCurrentVisibility = 0.0f; coronaCandidate.m_fLastVisibilityQuery = 0.0f; } } } } // Removes coronas that are outside the frustum and no longer visible. if ((iCoronaUpdateFlags & VCUF_REMOVE) > 0) { for (int i=0; i < state.m_Candidates.GetSize();) { VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i); VCoronaComponent* pCorona = coronaCandidate.m_pCorona; unsigned int iElementIndex = pCorona->m_CoronaPixelCounter.GetNumber(); // If the visibility reached zero and the corona is no longer potentially visible it is removed from the list if (!pCorona->IsEnabled() || !pCorona->GetOwner() || (pCorona->GetVisibleBitmask() & iRenderFilterMask) == 0 || (((VisLightSource_cl*)pCorona->GetOwner())->GetVisibleBitmask() & iRenderFilterMask) == 0 || ( coronaCandidate.m_fCurrentVisibility == 0.0f && !pCorona->IsValidCandidate(pContext) ) ) { state.RemoveBit(pCorona->m_iIndex); state.m_Candidates.SetAt(i, state.m_Candidates.GetAt(state.m_Candidates.GetSize()-1) ); state.m_Candidates.RemoveAt(state.m_Candidates.GetSize() -1); // Reset cache to zero, so we don't see the lens flare once it enters the frustum again. pContext->SetPixelCounterResult(iElementIndex, 0); } else { ++i; } } } #endif }
void VFakeSpecularGenerator::OnDoRenderLoop(void *pUserData) { VFrustumMeshHelper::UpdateMeshBuffer(m_spMeshBuffer, Vision::Contexts.GetCurrentContext(), VFrustumMeshHelper::IN_WORLD_SPACE); Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, VColorRef(0, 0, 0, 0)); VisRenderContext_cl* pContext = Vision::Contexts.GetCurrentContext(); const VisLightSrcCollection_cl* pLights = pContext->GetVisibilityCollector()->GetVisibleLights(); Vision::RenderLoopHelper.BeginMeshRendering(); Vision::RenderLoopHelper.ResetMeshStreams(); Vision::RenderLoopHelper.AddMeshStreams(m_spMeshBuffer, m_spShader->GetStreamMask () | VERTEX_STREAM_INDEXBUFFER); for(unsigned int iLightIndex = 0; iLightIndex < pLights->GetNumEntries(); iLightIndex++) { VisLightSource_cl* pLight = pLights->GetEntry(iLightIndex); if((pLight->GetVisibleBitmask() & pContext->GetRenderFilterMask()) == 0) continue; if(!pLight->GetUseSpecular()) continue; hkvVec4 vDirection; hkvVec3 vLightPositionRel = pLight->GetPosition() - pContext->GetCamera()->GetPosition(); hkvVec3 vLightDirection = pLight->GetDirection(); float fAttenuation = 1; switch(pLight->GetType()) { case VIS_LIGHT_DIRECTED: vDirection = vLightDirection.getAsVec4(1.0f); break; case VIS_LIGHT_SPOTLIGHT: { vDirection = vLightDirection.getAsVec4(1.0f); float fAngle = vLightPositionRel.getAngleBetween(-vLightDirection); float fConeAngle = pLight->GetProjectionAngle(); fAttenuation = hkvMath::clamp((fConeAngle - fAngle) / fConeAngle, 0.0f, 1.0f); float fDistance = vLightPositionRel.getLength(); float fRadius = pLight->GetRadius(); fAttenuation *= hkvMath::clamp((fRadius - fDistance) / fRadius, 0.0f, 1.0f); } break; case VIS_LIGHT_POINT: vDirection = (-vLightPositionRel).getNormalized().getAsVec4(1.0f); float fDistance = vLightPositionRel.getLength(); float fRadius = pLight->GetRadius(); fAttenuation = hkvMath::clamp((fRadius - fDistance) / fRadius, 0.0f, 1.0f); break; } hkvVec4 vColor = pLight->GetColor().getAsVec4() * pLight->GetMultiplier() * fAttenuation; hkvVec4 vParams(m_fSpecularPower, 0, 0, 0); m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fLightDirection", vDirection.data); m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fLightColor", vColor.data); m_spShader->GetConstantBuffer(VSS_PixelShader)->SetSingleParameterF("fParams", vParams.data); Vision::RenderLoopHelper.RenderMeshes(m_spShader, VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST, 0, 2, 6); } Vision::RenderLoopHelper.EndMeshRendering(); // Trigger pre-screenmask render hook to make the attached cubemap handle flip and blur the cubemap target VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook, VRH_PRE_SCREENMASKS); Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data); }