void FRCPassPostProcessVisualizeBuffer::AddVisualizationBuffer(FRenderingCompositeOutputRef InSource, const FString& InName) { Tiles.Add(TileData(InSource, InName)); if (InSource.IsValid()) { AddDependency(InSource); } }
void FRCPassPostProcessVisualizeBuffer::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(VisualizeBuffer, DEC_SCENE_ITEMS); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; FIntPoint SrcSize = InputDesc->Extent; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. RHISetRenderTarget(DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(DestRect); // set the state RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); SetShaderTempl<false>(Context); // Draw a quad mapping scene color to the view's render target DrawRectangle( 0, 0, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, EDRF_UseTriangleOptimization); // Now draw the requested tiles into the grid TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FPostProcessVisualizeBufferPS<true> > PixelShader(GetGlobalShaderMap()); RHISetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_SourceAlpha, BF_InverseSourceAlpha>::GetRHI()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetPS(Context); // Track the name and position of each tile we draw so we can write text labels over them struct LabelRecord { FString Label; int32 LocationX; int32 LocationY; }; TArray<LabelRecord> Labels; const int32 MaxTilesX = 4; const int32 MaxTilesY = 4; const int32 TileWidth = DestRect.Width() / MaxTilesX; const int32 TileHeight = DestRect.Height() / MaxTilesY; int32 CurrentTileIndex = 0; for (TArray<TileData>::TConstIterator It = Tiles.CreateConstIterator(); It; ++It, ++CurrentTileIndex) { FRenderingCompositeOutputRef Tile = It->Source; if (Tile.IsValid()) { FTextureRHIRef Texture = Tile.GetOutput()->PooledRenderTarget->GetRenderTargetItem().TargetableTexture; int32 TileX = CurrentTileIndex % MaxTilesX; int32 TileY = CurrentTileIndex / MaxTilesX; PixelShader->SetSourceTexture(Texture); DrawRectangle( TileX * TileWidth, TileY * TileHeight, TileWidth, TileHeight, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, EDRF_Default); Labels.Add(LabelRecord()); Labels.Last().Label = It->Name; Labels.Last().LocationX = 8 + TileX * TileWidth; Labels.Last().LocationY = (TileY + 1) * TileHeight - 19; } } // Draw tile labels // this is a helper class for FCanvas to be able to get screen size class FRenderTargetTemp : public FRenderTarget { public: const FSceneView& View; const FTexture2DRHIRef Texture; FRenderTargetTemp(const FSceneView& InView, const FTexture2DRHIRef InTexture) : View(InView), Texture(InTexture) { } virtual FIntPoint GetSizeXY() const { return View.ViewRect.Size(); }; virtual const FTexture2DRHIRef& GetRenderTargetTexture() const { return Texture; } } TempRenderTarget(View, (const FTexture2DRHIRef&)DestRenderTarget.TargetableTexture); FCanvas Canvas(&TempRenderTarget, NULL, ViewFamily.CurrentRealTime, ViewFamily.CurrentWorldTime, ViewFamily.DeltaWorldTime); FLinearColor LabelColor(1, 1, 0); for (auto It = Labels.CreateConstIterator(); It; ++It) { Canvas.DrawShadowedString(It->LocationX, It->LocationY, *It->Label, GetStatsFont(), LabelColor); } Canvas.Flush(); RHICopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }