void USceneCaptureComponentCube::UpdateDeferredCaptures( FSceneInterface* Scene ) { UWorld* World = Scene->GetWorld(); if( World && CubedSceneCapturesToUpdateMap.Num() > 0 ) { World->SendAllEndOfFrameUpdates(); // Only update the scene captures associated with the current scene. // Updating others not associated with the scene would cause invalid data to be rendered into the target TArray< TWeakObjectPtr<USceneCaptureComponentCube> > SceneCapturesToUpdate; CubedSceneCapturesToUpdateMap.MultiFind( World, SceneCapturesToUpdate ); for( TWeakObjectPtr<USceneCaptureComponentCube> Component : SceneCapturesToUpdate ) { if( Component.IsValid() ) { Scene->UpdateSceneCaptureContents( Component.Get() ); } } // All scene captures for this world have been updated CubedSceneCapturesToUpdateMap.Remove( World ); } }
void USceneCaptureComponent2D::UpdateDeferredCaptures( FSceneInterface* Scene ) { UWorld* World = Scene->GetWorld(); if( World && SceneCapturesToUpdateMap.Num() > 0 ) { // Only update the scene captures assoicated with the current scene. // Updating others not associated with the scene would cause invalid data to be rendered into the target TArray<USceneCaptureComponent2D*> SceneCapturesToUpdate; SceneCapturesToUpdateMap.MultiFind( World, SceneCapturesToUpdate ); for( USceneCaptureComponent2D* Component : SceneCapturesToUpdate ) { Scene->UpdateSceneCaptureContents( Component ); } // All scene captures for this world have been updated SceneCapturesToUpdateMap.Remove( World) ; } }
void FReferenceChainSearch::BuildRefGraph() { UE_LOG(LogReferenceChain, Log, TEXT("Generating reference graph ...")); bool bContinue = true; TMultiMap<UObject*, FRefGraphItem*> GraphNodes; // Create the first graph-nodes referencing the target object for (FRawObjectIterator It;It;++It) { UObject* Obj = *It; TArray<FReferenceChainLink>& RefList = ReferenceMap.FindChecked(Obj); for (int32 i=0; i < RefList.Num(); ++i) { if (RefList[i].ReferencedObj == ObjectToFind) { FRefGraphItem* Node = new FRefGraphItem(); Node->Link = RefList[i]; GraphNodes.Add(Node->Link.ReferencedBy, Node); RefList[i].ReferenceType = EReferenceType::Invalid; } } } int32 Level = 0; UE_LOG(LogReferenceChain, Log, TEXT("Level 0 has %d nodes ..."), GraphNodes.Num()); while(bContinue) { int32 AddedNodes = 0; TArray<FRefGraphItem*> NewGraphNodes; for (FRawObjectIterator It;It;++It) { UObject* Obj = *It; TArray<FReferenceChainLink>& RefList = ReferenceMap.FindChecked(Obj); for (int32 i=0; i < RefList.Num(); ++i) { if (RefList[i].ReferenceType == EReferenceType::Invalid || RefList[i].ReferencedObj->HasAnyFlags(GARBAGE_COLLECTION_KEEPFLAGS | RF_RootSet)) // references to rooted objects are not important { continue; } TArray<FRefGraphItem*> RefNodes; if (FindReferencedGraphNodes(GraphNodes, RefList[i].ReferencedObj, RefNodes) > 0) { FRefGraphItem* Node = FindNode(GraphNodes, RefList[i].ReferencedBy, RefList[i].ReferencedObj); if (Node == NULL) { Node = new FRefGraphItem(); Node->Link = RefList[i]; NewGraphNodes.Push(Node); } for (int32 j=0; j < RefNodes.Num(); ++j) { Node->Children.Push(RefNodes[j]); RefNodes[j]->Parents.Push(Node); } ++AddedNodes; RefList[i].ReferenceType = EReferenceType::Invalid; } } } Level++; UE_LOG(LogReferenceChain, Log, TEXT("Level %d added %d nodes ..."), Level, NewGraphNodes.Num()); for (int32 i = 0; i < NewGraphNodes.Num(); ++i) { GraphNodes.Add(NewGraphNodes[i]->Link.ReferencedBy, NewGraphNodes[i]); } NewGraphNodes.Empty(NewGraphNodes.Num()); bContinue = AddedNodes > 0; } TArray<FReferenceChain> Chains; UE_LOG(LogReferenceChain, Log, TEXT("Generating reference chains ...")); for (auto It = GraphNodes.CreateConstIterator(); It; ++It) { FRefGraphItem* Node = It.Value(); if (Node->Link.ReferencedBy->HasAnyFlags(GARBAGE_COLLECTION_KEEPFLAGS | RF_RootSet)) { FReferenceChain CurChain; CreateReferenceChain(Node, CurChain, Chains, ObjectToFind, Level); } } for (int32 i=0; i < Chains.Num(); ++i) { InsertReferenceChain(Chains[i]); } }
void FRCPassPostProcessSelectionOutlineColor::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSelectionOutlineBuffer, DEC_SCENE_ITEMS); const FPooledRenderTargetDesc* SceneColorInputDesc = GetInputDesc(ePId_Input0); if(!SceneColorInputDesc) { // input is not hooked up correctly return; } const FViewInfo& View = Context.View; FIntRect ViewRect = View.ViewRect; FIntPoint SrcSize = SceneColorInputDesc->Extent; // Get the output render target const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the render target/viewport. SetRenderTarget(Context.RHICmdList, FTextureRHIParamRef(), DestRenderTarget.TargetableTexture); // This is a reversed Z depth surface, so 0.0f is the far plane. Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); Context.SetViewportAndCallRHI(ViewRect); if (View.Family->EngineShowFlags.Selection) { const bool bUseGetMeshElements = ShouldUseGetDynamicMeshElements(); if (bUseGetMeshElements) { FHitProxyDrawingPolicyFactory::ContextType FactoryContext; //@todo - use memstack TMap<FName, int32> ActorNameToStencilIndex; ActorNameToStencilIndex.Add(NAME_BSP, 1); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); for (int32 MeshBatchIndex = 0; MeshBatchIndex < View.DynamicMeshElements.Num(); MeshBatchIndex++) { const FMeshBatchAndRelevance& MeshBatchAndRelevance = View.DynamicMeshElements[MeshBatchIndex]; const FPrimitiveSceneProxy* PrimitiveSceneProxy = MeshBatchAndRelevance.PrimitiveSceneProxy; if (PrimitiveSceneProxy->IsSelected() && MeshBatchAndRelevance.Mesh->bUseSelectionOutline) { const int32* AssignedStencilIndexPtr = ActorNameToStencilIndex.Find(PrimitiveSceneProxy->GetOwnerName()); if (!AssignedStencilIndexPtr) { AssignedStencilIndexPtr = &ActorNameToStencilIndex.Add(PrimitiveSceneProxy->GetOwnerName(), ActorNameToStencilIndex.Num() + 1); } // This is a reversed Z depth surface, using CF_GreaterEqual. // Note that the stencil value will overflow with enough selected objects Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), *AssignedStencilIndexPtr); const FMeshBatch& MeshBatch = *MeshBatchAndRelevance.Mesh; FHitProxyDrawingPolicyFactory::DrawDynamicMesh(Context.RHICmdList, View, FactoryContext, MeshBatch, false, true, MeshBatchAndRelevance.PrimitiveSceneProxy, MeshBatch.BatchHitProxyId); } } } else if (View.VisibleDynamicPrimitives.Num() > 0) { TDynamicPrimitiveDrawer<FHitProxyDrawingPolicyFactory> Drawer(Context.RHICmdList, &View, FHitProxyDrawingPolicyFactory::ContextType(), true, false, false, true); TMultiMap<FName, const FPrimitiveSceneInfo*> PrimitivesByActor; for (int32 PrimitiveIndex = 0; PrimitiveIndex < View.VisibleDynamicPrimitives.Num();PrimitiveIndex++) { const FPrimitiveSceneInfo* PrimitiveSceneInfo = View.VisibleDynamicPrimitives[PrimitiveIndex]; // Only draw the primitive if relevant if(PrimitiveSceneInfo->Proxy->IsSelected()) { PrimitivesByActor.Add(PrimitiveSceneInfo->Proxy->GetOwnerName(), PrimitiveSceneInfo); } } if (PrimitivesByActor.Num()) { // 0 means no object, 1 means BSP so we start with 2 uint32 StencilValue = 2; Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetBlendState(TStaticBlendStateWriteMask<CW_NONE, CW_NONE, CW_NONE, CW_NONE>::GetRHI()); // Sort by actor TArray<FName> Actors; PrimitivesByActor.GetKeys(Actors); for( TArray<FName>::TConstIterator ActorIt(Actors); ActorIt; ++ActorIt ) { bool bBSP = *ActorIt == NAME_BSP; if (bBSP) { // This is a reversed Z depth surface, using CF_GreaterEqual. Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), 1); } else { // This is a reversed Z depth surface, using CF_GreaterEqual. Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_GreaterEqual, true, CF_Always, SO_Keep, SO_Keep, SO_Replace>::GetRHI(), StencilValue); // we want to use 1..255 for all objects, not correct silhouettes after that is acceptable StencilValue = (StencilValue == 255) ? 2 : (StencilValue + 1); } TArray<const FPrimitiveSceneInfo*> Primitives; PrimitivesByActor.MultiFind(*ActorIt, Primitives); for( TArray<const FPrimitiveSceneInfo*>::TConstIterator PrimIt(Primitives); PrimIt; ++PrimIt ) { const FPrimitiveSceneInfo* PrimitiveSceneInfo = *PrimIt; // Render the object to the stencil/depth buffer Drawer.SetPrimitive(PrimitiveSceneInfo->Proxy); PrimitiveSceneInfo->Proxy->DrawDynamicElements(&Drawer, &View); } } } } // to get an outline around the objects if it's partly outside of the screen { FIntRect InnerRect = ViewRect; // 1 as we have an outline that is that thick InnerRect.InflateRect(-1); // We could use Clear with InnerRect but this is just an optimization - on some hardware it might do a full clear (and we cannot disable yet) // RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, InnerRect); // so we to 4 clears - one for each border. // top Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Max.X, InnerRect.Min.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // bottom Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, InnerRect.Max.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // left Context.RHICmdList.SetScissorRect(true, ViewRect.Min.X, ViewRect.Min.Y, InnerRect.Min.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); // right Context.RHICmdList.SetScissorRect(true, InnerRect.Max.X, ViewRect.Min.Y, ViewRect.Max.X, ViewRect.Max.Y); Context.RHICmdList.Clear(false, FLinearColor(0, 0, 0, 0), true, 0.0f, true, 0, FIntRect()); Context.RHICmdList.SetScissorRect(false, 0, 0, 0, 0); } } // Resolve to the output Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }