void FVulkanCommandListContext::InternalClearMRT(FVulkanCmdBuffer* CmdBuffer, bool bClearColor, int32 NumClearColors, const FLinearColor* ClearColorArray, bool bClearDepth, float Depth, bool bClearStencil, uint32 Stencil, FIntRect ExcludeRect) { #if VULKAN_USE_NEW_RENDERPASSES const VkExtent2D& Extents = RenderPassState.CurrentRenderPass->GetLayout().GetExtent2D(); if (ExcludeRect.Min.X == 0 && ExcludeRect.Width() == Extents.width && ExcludeRect.Min.Y == 0 && Extents.height) { //if (ForceFullScreen == EForceFullScreenClear::EDoNotForce) { return; } //else { //ensureMsgf(false, TEXT("Forced Full Screen Clear ignoring Exclude Rect Restriction")); } } ensure(ExcludeRect.Area() == 0); if (RenderPassState.CurrentRenderPass) { VkClearRect Rect; FMemory::Memzero(Rect); Rect.rect.offset.x = 0; Rect.rect.offset.y = 0; Rect.rect.extent = Extents; VkClearAttachment Attachments[MaxSimultaneousRenderTargets + 1]; FMemory::Memzero(Attachments); uint32 NumAttachments = NumClearColors; if (bClearColor) { for (int32 i = 0; i < NumClearColors; ++i) { Attachments[i].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; Attachments[i].colorAttachment = i; Attachments[i].clearValue.color.float32[0] = ClearColorArray[i].R; Attachments[i].clearValue.color.float32[1] = ClearColorArray[i].G; Attachments[i].clearValue.color.float32[2] = ClearColorArray[i].B; Attachments[i].clearValue.color.float32[3] = ClearColorArray[i].A; } } if (bClearDepth || bClearStencil) { Attachments[NumClearColors].aspectMask = bClearDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0; Attachments[NumClearColors].aspectMask |= bClearStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0; Attachments[NumClearColors].colorAttachment = 0; Attachments[NumClearColors].clearValue.depthStencil.depth = Depth; Attachments[NumClearColors].clearValue.depthStencil.stencil = Stencil; ++NumAttachments; } VulkanRHI::vkCmdClearAttachments(CmdBuffer->GetHandle(), NumAttachments, Attachments, 1, &Rect); } else { ensure(0); //VulkanRHI::vkCmdClearColorImage(CmdBuffer->GetHandle(), ) } #else #if VULKAN_ALLOW_MIDPASS_CLEAR const VkExtent2D& Extents = PendingState->GetRenderPass().GetLayout().GetExtent2D(); if (ExcludeRect.Min.X == 0 && ExcludeRect.Width() == Extents.width && ExcludeRect.Min.Y == 0 && Extents.height) { //if (ForceFullScreen == EForceFullScreenClear::EDoNotForce) { return; } //else { //ensureMsgf(false, TEXT("Forced Full Screen Clear ignoring Exclude Rect Restriction")); } } ensure(ExcludeRect.Area() == 0); VkClearRect Rect; FMemory::Memzero(Rect); Rect.rect.offset.x = 0; Rect.rect.offset.y = 0; Rect.rect.extent = PendingState->GetRenderPass().GetLayout().GetExtent2D(); VkClearAttachment Attachments[MaxSimultaneousRenderTargets + 1]; FMemory::Memzero(Attachments); uint32 NumAttachments = NumClearColors; if (bClearColor) { for (int32 i = 0; i < NumClearColors; ++i) { Attachments[i].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; Attachments[i].colorAttachment = i; Attachments[i].clearValue.color.float32[0] = ClearColorArray[i].R; Attachments[i].clearValue.color.float32[1] = ClearColorArray[i].G; Attachments[i].clearValue.color.float32[2] = ClearColorArray[i].B; Attachments[i].clearValue.color.float32[3] = ClearColorArray[i].A; } } if(bClearDepth || bClearStencil) { Attachments[NumClearColors].aspectMask = bClearDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0; Attachments[NumClearColors].aspectMask |= bClearStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0; Attachments[NumClearColors].colorAttachment = 0; Attachments[NumClearColors].clearValue.depthStencil.depth = Depth; Attachments[NumClearColors].clearValue.depthStencil.stencil = Stencil; ++NumAttachments; } VulkanRHI::vkCmdClearAttachments(CmdBuffer->GetHandle(), NumAttachments, Attachments, 1, &Rect); #endif #endif }
void FRCPassPostProcessSubsurfaceRecombine::Process(FRenderingCompositePassContext& Context) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); check(InputDesc); const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = SceneContext.GetBufferSizeXY(); check(DestSize.X); check(DestSize.Y); check(SrcSize.X); check(SrcSize.Y); FIntRect SrcRect = FIntRect(0, 0, InputDesc->Extent.X, InputDesc->Extent.Y); FIntRect DestRect = View.ViewRect; TRefCountPtr<IPooledRenderTarget>& SceneColor = SceneContext.GetSceneColor(); const FSceneRenderTargetItem& DestRenderTarget = SceneColor->GetRenderTargetItem(); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGBA,BO_Add,BF_SourceAlpha,BF_InverseSourceAlpha,BO_Add,BF_SourceAlpha,BF_InverseSourceAlpha>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); bool bDoSpecularCorrection = DoSpecularCorrection(); SCOPED_DRAW_EVENTF(Context.RHICmdList, SubsurfacePass, TEXT("SubsurfacePassRecombine#%d"), (int32)bDoSpecularCorrection); if(bDoSpecularCorrection) { SetSubsurfaceRecombineShader<1>(Context, VertexShader); } else { SetSubsurfaceRecombineShader<0>(Context, VertexShader); } DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FSubtitleManager::DisplaySubtitle( FCanvas* Canvas, FActiveSubtitle* Subtitle, FIntRect& Parms, const FLinearColor& Color ) { // These should be valid in here check( GEngine ); check( Canvas ); CurrentSubtitleHeight = 0.0f; // This can be NULL when there's an asset mixup (especially with localisation) if( !GEngine->GetSubtitleFont() ) { UE_LOG(LogSubtitle, Warning, TEXT( "NULL GEngine->GetSubtitleFont() - subtitles not rendering!" ) ); return; } float FontHeight = GEngine->GetSubtitleFont()->GetMaxCharHeight(); float HeightTest = Canvas->GetRenderTarget()->GetSizeXY().Y; int32 SubtitleHeight = FMath::TruncToInt( ( FontHeight * MULTILINE_SPACING_SCALING ) ); FIntRect BackgroundBoxOffset = DrawStringOutlineBoxOffset; // Needed to add a drop shadow and doing all 4 sides was the only way to make them look correct. If this shows up as a framerate hit we'll have to think of a different way of dealing with this. if( Subtitle->bSingleLine ) { if ( !( Subtitle->Subtitles[Subtitle->Index].Text.IsEmpty() ) ) { // Display lines up from the bottom of the region Parms.Max.Y -= SUBTITLE_CHAR_HEIGHT; FCanvasTextItem TextItem( FVector2D( Parms.Min.X + ( Parms.Width() / 2 ), Parms.Max.Y ), Subtitle->Subtitles[ Subtitle->Index ].Text , GEngine->GetSubtitleFont(), Color ); TextItem.Depth = SUBTITLE_SCREEN_DEPTH_FOR_3D; TextItem.bOutlined = true; TextItem.bCentreX = true; TextItem.OutlineColor = FLinearColor::Black; Canvas->DrawItem( TextItem ); CurrentSubtitleHeight += SubtitleHeight; } } else { for( int32 Idx = Subtitle->Subtitles.Num() - 1; Idx >= 0; Idx-- ) { // Display lines up from the bottom of the region if ( !( Subtitle->Subtitles[Idx].Text.IsEmpty() ) ) { FCanvasTextItem TextItem( FVector2D( Parms.Min.X + ( Parms.Width() / 2 ), Parms.Max.Y ), Subtitle->Subtitles[ Subtitle->Index ].Text, GEngine->GetSubtitleFont(), Color ); TextItem.Depth = SUBTITLE_SCREEN_DEPTH_FOR_3D; TextItem.bOutlined = true; TextItem.bCentreX = true; TextItem.OutlineColor = FLinearColor::Black; Canvas->DrawItem( TextItem ); Parms.Max.Y -= SubtitleHeight; CurrentSubtitleHeight += SubtitleHeight; // Don't overlap subsequent boxes... BackgroundBoxOffset.Max.Y = BackgroundBoxOffset.Min.Y; } } } }
void FRCPassPostProcessMaterial::Process(FRenderingCompositePassContext& Context) { FMaterialRenderProxy* Proxy = MaterialInterface->GetRenderProxy(false); check(Proxy); const FMaterial* Material = Proxy->GetMaterial(Context.View.GetFeatureLevel()); check(Material); SCOPED_DRAW_EVENTF(Context.RHICmdList, PostProcessMaterial, TEXT("PostProcessMaterial Material=%s"), *Material->GetFriendlyName()); 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); // hacky cast FRenderingCompositePassContext RenderingCompositePassContext(Context.RHICmdList, (FViewInfo&)View); RenderingCompositePassContext.Pass = this; 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. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIParamRef()); if( ViewFamily.RenderTarget->GetRenderTargetTexture() != DestRenderTarget.TargetableTexture ) { Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, View.ViewRect); } Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); float ScaleX = 1.0f / InputDesc->Extent.X; float ScaleY = 1.0f / InputDesc->Extent.Y; const FMaterialShaderMap* MaterialShaderMap = Material->GetRenderingThreadShaderMap(); FPostProcessMaterialPS* PixelShader = MaterialShaderMap->GetShader<FPostProcessMaterialPS>(); FPostProcessMaterialVS* VertexShader = MaterialShaderMap->GetShader<FPostProcessMaterialVS>(); Context.RHICmdList.SetLocalBoundShaderState(Context.RHICmdList.BuildLocalBoundShaderState(GetVertexDeclarationFVector4(), VertexShader->GetVertexShader(), FHullShaderRHIRef(), FDomainShaderRHIRef(), PixelShader->GetPixelShader(), FGeometryShaderRHIRef())); VertexShader->SetParameters(Context.RHICmdList, Context); PixelShader->SetParameters(Context.RHICmdList, Context, MaterialInterface->GetRenderProxy(false)); DrawRectangle( Context.RHICmdList, 0, 0, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); if(Material->NeedsGBuffer()) { GSceneRenderTargets.AdjustGBufferRefCount(-1); } }
void FRCPassPostProcessDOFRecombine::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, DOFRecombine); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input1); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; const auto FeatureLevel = Context.GetFeatureLevel(); auto ShaderMap = Context.GetShaderMap(); FIntPoint TexSize = InputDesc->Extent; // usually 1, 2, 4 or 8 uint32 ScaleToFullRes = GSceneRenderTargets.GetBufferSizeXY().X / TexSize.X; FIntRect HalfResViewRect = View.ViewRect / ScaleToFullRes; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); // is optimized away if possible (RT size=view size, ) Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, View.ViewRect); Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap); if (bNearBlurEnabled) { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFRecombinePS<1> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFRecombinePS<0> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } VertexShader->SetParameters(Context); // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), HalfResViewRect.Min.X, HalfResViewRect.Min.Y, HalfResViewRect.Width(), HalfResViewRect.Height(), View.ViewRect.Size(), TexSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessNoiseBlur::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(NoiseBlur, 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); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. RHISetRenderTarget(DestRenderTarget.TargetableTexture, FTextureRHIRef()); // is optimized away if possible (RT size=view size, ) RHIClear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); if(Quality == 0) { SetNoiseBlurShader<0>(Context, Radius); } else if(Quality == 1) { SetNoiseBlurShader<1>(Context, Radius); } else { SetNoiseBlurShader<2>(Context, Radius); } // Draw a quad mapping scene color to the view's render target DrawRectangle( DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, EDRF_UseTriangleOptimization); RHICopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessMotionBlur::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, MotionBlur); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; FIntPoint TexSize = InputDesc->Extent; // we assume the input and output is full resolution FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = FIntRect::DivideAndRoundUp(View.ViewRect, ScaleFactor); FIntRect DestRect = SrcRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); // is optimized away if possible (RT size=view size, ) Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, SrcRect); Context.SetViewportAndCallRHI(SrcRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); if(Quality == 1) { SetMotionBlurShaderTempl<1>(Context); } else if(Quality == 2) { SetMotionBlurShaderTempl<2>(Context); } else if(Quality == 3) { SetMotionBlurShaderTempl<3>(Context); } else { check(Quality == 4); SetMotionBlurShaderTempl<4>(Context); } TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, 0, 0, SrcRect.Width(), SrcRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), SrcRect.Size(), SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessTestImage::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, TestImage); const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(DestRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef<FPostProcessTestImagePS> PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetPS(Context); // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, 0, 0, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY(), *VertexShader, EDRF_UseTriangleOptimization); { // 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, Context.GetFeatureLevel()); float X = 30; float Y = 8; const float YStep = 14; const float ColumnWidth = 250; FString Line; Line = FString::Printf(TEXT("Top bars:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Moving bars using FrameTime")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Black and white raster, Pixel sized, Watch for Moire pattern")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Black and white raster, 2x2 block sized")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT("Bottom bars:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" 8 bars near white, 4 right bars should appear as one (HDTV)")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" 8 bars near black, 4 left bars should appear as one (HDTV)")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Linear Greyscale in sRGB from 0 to 255")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT("Color bars:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Red, Green, Blue")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT("Outside:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Moving bars using FrameNumber, Tearing without VSync")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT("Circles:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" Should be round and centered")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT("Border:")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Line = FString::Printf(TEXT(" 4 white pixel sized lines (only visible without overscan)")); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Canvas.Flush_RenderThread(Context.RHICmdList); } Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessDOFSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, DOFSetup); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } uint32 NumRenderTargets = bNearBlurEnabled ? 2 : 1; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); const auto FeatureLevel = Context.GetFeatureLevel(); auto ShaderMap = Context.GetShaderMap(); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect / 2; const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = bNearBlurEnabled ? PassOutputs[1].RequestSurface(Context) : FSceneRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[2] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, FTextureRHIParamRef(), 0, NULL); FLinearColor ClearColors[2] = { FLinearColor(0, 0, 0, 0), FLinearColor(0, 0, 0, 0) }; // is optimized away if possible (RT size=view size, ) Context.RHICmdList.ClearMRT(true, NumRenderTargets, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(DestRect.Min.X, DestRect.Min.Y, 0.0f, DestRect.Max.X + 1, DestRect.Max.Y + 1, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap); if (bNearBlurEnabled) { const float DOFVignetteSize = FMath::Max(0.0f, View.FinalPostProcessSettings.DepthOfFieldVignetteSize); // todo: test is conservative, with bad content we would waste a bit of performance const bool bDOFVignette = DOFVignetteSize < 200.0f; if(bDOFVignette) { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<2> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<1> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessDOFSetupPS<0> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } VertexShader->SetParameters(Context); DrawPostProcessPass( Context.RHICmdList, 0, 0, DestRect.Width() + 1, DestRect.Height() + 1, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width() + 1, SrcRect.Height() + 1, DestRect.Size() + FIntPoint(1, 1), SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessSubsurface::Process(FRenderingCompositePassContext& Context) { const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); check(InputDesc); { const IPooledRenderTarget* PooledRT = GetSubsufaceProfileTexture_RT(Context.RHICmdList); check(PooledRT); // for debugging GRenderTargetPool.VisualizeTexture.SetCheckPoint(Context.RHICmdList, PooledRT); } const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; check(DestSize.X); check(DestSize.Y); check(SrcSize.X); check(SrcSize.Y); FIntRect SrcRect = FIntRect(0, 0, DestSize.X, DestSize.Y); FIntRect DestRect = SrcRect; TRefCountPtr<IPooledRenderTarget> NewSceneColor; const FSceneRenderTargetItem* DestRenderTarget; { DestRenderTarget = &PassOutputs[0].RequestSurface(Context); check(DestRenderTarget); } // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget->TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); SCOPED_DRAW_EVENTF(Context.RHICmdList, SubsurfacePass, TEXT("SubsurfaceDirection#%d"), Direction); uint32 SampleSet = FMath::Clamp(CVarSSSSampleSet.GetValueOnRenderThread(), 0, 2); if (Direction == 0) { SetSubsurfaceShaderSampleSet<0>(Context, VertexShader, SampleSet); } else { SetSubsurfaceShaderSampleSet<1>(Context, VertexShader, SampleSet); } DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget->TargetableTexture, DestRenderTarget->ShaderResourceTexture, false, FResolveParams()); }
void FTileSetEditorViewportClient::Draw(FViewport* Viewport, FCanvas* Canvas) { // Clear the viewport Canvas->Clear(GetBackgroundColor()); // Can only proceed if we have a valid tile set UPaperTileSet* TileSet = TileSetBeingEdited.Get(); if (TileSet == nullptr) { return; } if (UTexture2D* Texture = TileSet->GetTileSheetTexture()) { const bool bUseTranslucentBlend = Texture->HasAlphaChannel(); // Fully stream in the texture before drawing it. Texture->SetForceMipLevelsToBeResident(30.0f); Texture->WaitForStreaming(); FLinearColor TextureDrawColor = FLinearColor::White; { // Draw the tile sheet texture const float XPos = -ZoomPos.X * ZoomAmount; const float YPos = -ZoomPos.Y * ZoomAmount; const float Width = Texture->GetSurfaceWidth() * ZoomAmount; const float Height = Texture->GetSurfaceHeight() * ZoomAmount; Canvas->DrawTile(XPos, YPos, Width, Height, 0.0f, 0.0f, 1.0f, 1.0f, TextureDrawColor, Texture->Resource, bUseTranslucentBlend); } const FLinearColor BorderRectangleColor(0.3f, 0.3f, 0.3f, 1.0f); { const FIntPoint TextureSize = Texture->GetImportedSize(); const FIntMargin BorderSize = TileSet->GetMargin(); const FIntRect TileSetRegion(BorderSize.Left, BorderSize.Top, TextureSize.X - BorderSize.Right, TextureSize.Y - BorderSize.Bottom); const float X = (TileSetRegion.Min.X - ZoomPos.X) * ZoomAmount; const float Y = (TileSetRegion.Min.Y - ZoomPos.Y) * ZoomAmount; const float W = TileSetRegion.Width() * ZoomAmount; const float H = TileSetRegion.Height() * ZoomAmount; FCanvasBoxItem BoxItem(FVector2D(X, Y), FVector2D(W, H)); BoxItem.SetColor(BorderRectangleColor); Canvas->DrawItem(BoxItem); } if (bShowTilesWithCollision || bShowTilesWithMetaData) { // Draw an overlay rectangle on top of any tiles that have collision or metadata geometry const int32 NumTiles = TileSet->GetTileCount(); const FLinearColor CollisionOverlayColor(0.0f, 0.7f, 1.0f, 0.5f); const FLinearColor MetaDataOverlayColor(1.0f, 0.2f, 0.0f, 0.5f); const FLinearColor InfoOverlayColor = bShowTilesWithCollision ? CollisionOverlayColor : MetaDataOverlayColor; const FIntPoint TileSetTileSize(TileSet->GetTileSize()); const float Width = (TileSetTileSize.X - 2) * ZoomAmount; const float Height = (TileSetTileSize.Y - 2) * ZoomAmount; for (int32 TileIndex = 0; TileIndex < NumTiles; ++TileIndex) { if (const FPaperTileMetadata* TileMetadata = TileSet->GetTileMetadata(TileIndex)) { const bool bShowDueToCollision = TileMetadata->HasCollision() && bShowTilesWithCollision; const bool bShowDueToMetaData = TileMetadata->HasMetaData() && bShowTilesWithMetaData; if (bShowDueToCollision || bShowDueToMetaData) { FVector2D TileUV; TileSet->GetTileUV(TileIndex, /*out*/ TileUV); const float XPos = (TileUV.X + 1 - ZoomPos.X) * ZoomAmount; const float YPos = (TileUV.Y + 1 - ZoomPos.Y) * ZoomAmount; Canvas->DrawTile(XPos, YPos, Width, Height, 0.0f, 0.0f, 1.0f, 1.0f, InfoOverlayColor, GWhiteTexture, /*bUseTranslucentBlend=*/ true); } } } } } // Overlay the selection rectangles DrawSelectionRectangles(Viewport, Canvas); if (bHasValidPaintRectangle) { const FViewportSelectionRectangle& Rect = ValidPaintRectangle; const float X = (Rect.TopLeft.X - ZoomPos.X) * ZoomAmount; const float Y = (Rect.TopLeft.Y - ZoomPos.Y) * ZoomAmount; const float W = Rect.Dimensions.X * ZoomAmount; const float H = Rect.Dimensions.Y * ZoomAmount; FCanvasBoxItem BoxItem(FVector2D(X, Y), FVector2D(W, H)); BoxItem.SetColor(Rect.Color); Canvas->DrawItem(BoxItem); } if (CurrentSelectedTileIndex != INDEX_NONE) { const FString TileIndexString = FString::Printf(TEXT("Tile# %d"), CurrentSelectedTileIndex); int32 XL; int32 YL; StringSize(GEngine->GetLargeFont(), XL, YL, *TileIndexString); const float DrawX = 4.0f; const float DrawY = FMath::FloorToFloat(Viewport->GetSizeXY().Y - YL - 4.0f); Canvas->DrawShadowedString(DrawX, DrawY, *TileIndexString, GEngine->GetLargeFont(), FLinearColor::White); } }
void FRCPassPostProcessSubsurfaceSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, SubsurfaceSetup); 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); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; FIntRect DestRect = FIntRect(0, 0, DestSize.X, DestSize.Y); // upscale rectangle to not slightly scale (might miss a pixel) FIntRect SrcRect = DestRect * 2 + View.ViewRect.Min; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); // reconstruct specular and add it in final pass bool bSpecularCorrection = DoSpecularCorrection(); if(bSpecularCorrection) { SetSubsurfaceSetupShader<1>(Context); } else { SetSubsurfaceSetupShader<0>(Context); } // Draw a quad mapping scene color to the view's render target TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessSubsurfaceExtractSpecular::Process(FRenderingCompositePassContext& Context) { const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); check(InputDesc); const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; check(DestSize.X); check(DestSize.Y); check(SrcSize.X); check(SrcSize.Y); // FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect SrcRect = View.ViewRect; FIntRect DestRect = View.ViewRect; TRefCountPtr<IPooledRenderTarget> NewSceneColor; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); bool bDoSpecularCorrection = DoSpecularCorrection(); SCOPED_DRAW_EVENTF(Context.RHICmdList, SubsurfacePass, TEXT("SubsurfacePassExtractSpecular#%d"), (int32)bDoSpecularCorrection); uint32 SampleSet = FMath::Clamp(CVarSSSSampleSet.GetValueOnRenderThread(), 0, 2); if(bDoSpecularCorrection) { SetSubsurfaceExtractSpecular<1>(Context, SampleSet); } else { SetSubsurfaceExtractSpecular<0>(Context, SampleSet); } DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessSubsurfaceVisualize::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, SubsurfaceSetup); 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); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = SceneContext.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); // is optimized away if possible (RT size=view size, ) Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); SetSubsurfaceVisualizeShader(Context); // Draw a quad mapping scene color to the view's render target TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); { // 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, Context.GetFeatureLevel()); float X = 30; float Y = 28; const float YStep = 14; FString Line; Line = FString::Printf(TEXT("Visualize Screen Space Subsurface Scattering")); Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); Y += YStep; uint32 Index = 0; while (GSubsurfaceProfileTextureObject.GetEntryString(Index++, Line)) { Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } Canvas.Flush_RenderThread(Context.RHICmdList); } Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); // we no longer need the GBuffer SceneContext.AdjustGBufferRefCount(-1); }
void FRCPassPostProcessDownsample::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, Downsample); 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); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = FSceneRenderTargets::Get(Context.RHICmdList).GetBufferSizeXY().X / SrcSize.X; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); // InflateSize increases the size of the source/dest rectangle to compensate for bilinear reads and UIBlur pass requirements. int32 InflateSize; // if second input is hooked up if (IsDepthInputAvailable()) { // also put depth in alpha InflateSize = 2; SetShader<2>(Context); } else { if (Quality == 0) { SetShader<0>(Context); InflateSize = 1; } else { SetShader<1>(Context); InflateSize = 2; } } bool bHasCleared = false; // check if we have to clear the whole surface. // Otherwise perform the clear when the dest rectangle has been computed. auto FeatureLevel = Context.View.GetFeatureLevel(); if (FeatureLevel == ERHIFeatureLevel::ES2 || FeatureLevel == ERHIFeatureLevel::ES3_1) { Context.RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, FIntRect()); bHasCleared = true; } TShaderMapRef<FPostProcessDownsampleVS> VertexShader(Context.GetShaderMap()); FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = FIntRect::DivideAndRoundUp(SrcRect, 2); SrcRect = DestRect * 2; if (!bHasCleared) { Context.RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, DestRect); } DrawPostProcessPass( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, *VertexShader, View.StereoPass, Context.HasHmdMesh(), EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessWeightedSampleSum::Process(FRenderingCompositePassContext& Context) { const FSceneView& View = Context.View; FRenderingCompositeOutput *Input = GetInput(ePId_Input0)->GetOutput(); // input is not hooked up correctly check(Input); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); // input is not hooked up correctly check(InputDesc); const FSceneViewFamily& ViewFamily = *(View.Family); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); // e.g. 4 means the input texture is 4x smaller than the buffer size FIntPoint SrcScaleFactor = SceneContext.GetBufferSizeXY() / SrcSize; FIntPoint DstScaleFactor = SceneContext.GetBufferSizeXY() / DestSize; TRefCountPtr<IPooledRenderTarget> InputPooledElement = Input->RequestInput(); check(!InputPooledElement->IsFree()); const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); bool bDoFastBlur = DoFastBlur(); FVector2D InvSrcSize(1.0f / SrcSize.X, 1.0f / SrcSize.Y); // we scale by width because FOV is defined horizontally float SrcSizeForThisAxis = View.ViewRect.Width() / (float)SrcScaleFactor.X; if(bDoFastBlur && FilterShape == EFS_Vert) { SrcSizeForThisAxis *= 2.0f; } // in texel (input resolution), /2 as we use the diameter, 100 as we use percent float EffectiveBlurRadius = SizeScale * SrcSizeForThisAxis / 2 / 100.0f; FVector2D BlurOffsets[MAX_FILTER_SAMPLES]; FLinearColor BlurWeights[MAX_FILTER_SAMPLES]; FVector2D OffsetAndWeight[MAX_FILTER_SAMPLES]; const auto FeatureLevel = Context.View.GetFeatureLevel(); // compute 1D filtered samples uint32 MaxNumSamples = GetMaxNumSamples(FeatureLevel); uint32 NumSamples = Compute1DGaussianFilterKernel(FeatureLevel, EffectiveBlurRadius, OffsetAndWeight, MaxNumSamples, FilterShape, CrossCenterWeight); FIntRect DestRect = FIntRect::DivideAndRoundUp(View.ViewRect, DstScaleFactor); SCOPED_DRAW_EVENTF(Context.RHICmdList, PostProcessWeightedSampleSum, TEXT("PostProcessWeightedSampleSum#%d %dx%d in %dx%d"), NumSamples, DestRect.Width(), DestRect.Height(), DestSize.X, DestSize.Y); // compute weights as weighted contributions of the TintValue for(uint32 i = 0; i < NumSamples; ++i) { BlurWeights[i] = TintValue * OffsetAndWeight[i].Y; } SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EExistingColorAndDepth); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f); bool bRequiresClear = true; // check if we have to clear the whole surface. // Otherwise perform the clear when the dest rectangle has been computed. if (FeatureLevel == ERHIFeatureLevel::ES2 || FeatureLevel == ERHIFeatureLevel::ES3_1) { Context.RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, FIntRect()); bRequiresClear = false; } FIntRect SrcRect = FIntRect::DivideAndRoundUp(View.ViewRect, SrcScaleFactor); if (bRequiresClear) { DrawClear(Context.RHICmdList, FeatureLevel, bDoFastBlur, SrcRect, DestRect, DestSize); } // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); const FTextureRHIRef& FilterTexture = InputPooledElement->GetRenderTargetItem().ShaderResourceTexture; FRenderingCompositeOutputRef* NodeInput1 = GetInput(ePId_Input1); FRenderingCompositeOutput *Input1 = NodeInput1 ? NodeInput1->GetOutput() : 0; uint32 CombineMethodInt = 0; if(CombineMethod == EFCM_MaxMagnitude) { CombineMethodInt = 2; } // can be optimized FTextureRHIRef AdditiveTexture; if(Input1) { TRefCountPtr<IPooledRenderTarget> InputPooledElement1 = Input1->RequestInput(); AdditiveTexture = InputPooledElement1->GetRenderTargetItem().ShaderResourceTexture; check(CombineMethod == EFCM_Weighted); CombineMethodInt = 1; } if (FilterShape == EFS_Horiz) { float YOffset = bDoFastBlur ? (InvSrcSize.Y * 0.5f) : 0.0f; for (uint32 i = 0; i < NumSamples; ++i) { BlurOffsets[i] = FVector2D(InvSrcSize.X * OffsetAndWeight[i].X, YOffset); } } else { float YOffset = bDoFastBlur ? -(InvSrcSize.Y * 0.5f) : 0.0f; for (uint32 i = 0; i < NumSamples; ++i) { BlurOffsets[i] = FVector2D(0, InvSrcSize.Y * OffsetAndWeight[i].X + YOffset); } } FShader* VertexShader = nullptr; SetFilterShaders( Context.RHICmdList, FeatureLevel, TStaticSamplerState<SF_Bilinear,AM_Border,AM_Border,AM_Clamp>::GetRHI(), FilterTexture, AdditiveTexture, CombineMethodInt, BlurOffsets, BlurWeights, NumSamples, &VertexShader ); DrawQuad(Context.RHICmdList, FeatureLevel, bDoFastBlur, SrcRect, DestRect, DestSize, SrcSize, VertexShader); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void ComputeDiffuseIrradiance(FRHICommandListImmediate& RHICmdList, ERHIFeatureLevel::Type FeatureLevel, FTextureRHIRef LightingSource, int32 LightingSourceMipIndex, FSHVectorRGB3* OutIrradianceEnvironmentMap) { auto ShaderMap = GetGlobalShaderMap(FeatureLevel); FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); for (int32 CoefficientIndex = 0; CoefficientIndex < FSHVector3::MaxSHBasis; CoefficientIndex++) { // Copy the starting mip from the lighting texture, apply texel area weighting and appropriate SH coefficient { const int32 MipIndex = 0; const int32 MipSize = GDiffuseIrradianceCubemapSize; FSceneRenderTargetItem& EffectiveRT = GetEffectiveDiffuseIrradianceRenderTarget(SceneContext, MipIndex); for (int32 CubeFace = 0; CubeFace < CubeFace_MAX; CubeFace++) { SetRenderTarget(RHICmdList, EffectiveRT.TargetableTexture, 0, CubeFace, NULL); const FIntRect ViewRect(0, 0, MipSize, MipSize); RHICmdList.SetViewport(0, 0, 0.0f, MipSize, MipSize, 1.0f); RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); TShaderMapRef<FCopyDiffuseIrradiancePS> PixelShader(ShaderMap); TShaderMapRef<FScreenVS> VertexShader(GetGlobalShaderMap(FeatureLevel)); SetGlobalBoundShaderState(RHICmdList, FeatureLevel, CopyDiffuseIrradianceShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, CubeFace, LightingSourceMipIndex, CoefficientIndex, MipSize, LightingSource); DrawRectangle( RHICmdList, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), FIntPoint(ViewRect.Width(), ViewRect.Height()), FIntPoint(MipSize, MipSize), *VertexShader); RHICmdList.CopyToResolveTarget(EffectiveRT.TargetableTexture, EffectiveRT.ShaderResourceTexture, true, FResolveParams(FResolveRect(), (ECubeFace)CubeFace, MipIndex)); } } const int32 NumMips = FMath::CeilLogTwo(GDiffuseIrradianceCubemapSize) + 1; { // Accumulate all the texel values through downsampling to 1x1 mip for (int32 MipIndex = 1; MipIndex < NumMips; MipIndex++) { const int32 SourceMipIndex = FMath::Max(MipIndex - 1, 0); const int32 MipSize = 1 << (NumMips - MipIndex - 1); FSceneRenderTargetItem& EffectiveRT = GetEffectiveDiffuseIrradianceRenderTarget(SceneContext, MipIndex); FSceneRenderTargetItem& EffectiveSource = GetEffectiveDiffuseIrradianceSourceTexture(SceneContext, MipIndex); check(EffectiveRT.TargetableTexture != EffectiveSource.ShaderResourceTexture); for (int32 CubeFace = 0; CubeFace < CubeFace_MAX; CubeFace++) { SetRenderTarget(RHICmdList, EffectiveRT.TargetableTexture, MipIndex, CubeFace, NULL); const FIntRect ViewRect(0, 0, MipSize, MipSize); RHICmdList.SetViewport(0, 0, 0.0f, MipSize, MipSize, 1.0f); RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); TShaderMapRef<FAccumulateDiffuseIrradiancePS> PixelShader(ShaderMap); TShaderMapRef<FScreenVS> VertexShader(GetGlobalShaderMap(FeatureLevel)); SetGlobalBoundShaderState(RHICmdList, FeatureLevel, DiffuseIrradianceAccumulateShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, CubeFace, NumMips, SourceMipIndex, CoefficientIndex, EffectiveSource.ShaderResourceTexture); DrawRectangle( RHICmdList, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), FIntPoint(ViewRect.Width(), ViewRect.Height()), FIntPoint(MipSize, MipSize), *VertexShader); RHICmdList.CopyToResolveTarget(EffectiveRT.TargetableTexture, EffectiveRT.ShaderResourceTexture, true, FResolveParams(FResolveRect(), (ECubeFace)CubeFace, MipIndex)); } } } { // Gather the cubemap face results and normalize, copy this coefficient to FSceneRenderTargets::Get(RHICmdList).SkySHIrradianceMap FSceneRenderTargetItem& EffectiveRT = FSceneRenderTargets::Get(RHICmdList).SkySHIrradianceMap->GetRenderTargetItem(); //load/store actions so we don't lose results as we render one pixel at a time on tile renderers. FRHIRenderTargetView RTV(EffectiveRT.TargetableTexture, 0, -1, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore); RHICmdList.SetRenderTargets(1, &RTV, nullptr, 0, nullptr); const FIntRect ViewRect(CoefficientIndex, 0, CoefficientIndex + 1, 1); RHICmdList.SetViewport(0, 0, 0.0f, FSHVector3::MaxSHBasis, 1, 1.0f); RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); TShaderMapRef<FScreenVS> VertexShader(ShaderMap); TShaderMapRef<FAccumulateCubeFacesPS> PixelShader(ShaderMap); SetGlobalBoundShaderState(RHICmdList, FeatureLevel, AccumulateCubeFacesBoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); const int32 SourceMipIndex = NumMips - 1; const int32 MipSize = 1; FSceneRenderTargetItem& EffectiveSource = GetEffectiveDiffuseIrradianceRenderTarget(SceneContext, SourceMipIndex); PixelShader->SetParameters(RHICmdList, SourceMipIndex, EffectiveSource.ShaderResourceTexture); DrawRectangle( RHICmdList, ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), 0, 0, MipSize, MipSize, FIntPoint(FSHVector3::MaxSHBasis, 1), FIntPoint(MipSize, MipSize), *VertexShader); RHICmdList.CopyToResolveTarget(EffectiveRT.TargetableTexture, EffectiveRT.ShaderResourceTexture, true, FResolveParams()); } } { // Read back the completed SH environment map FSceneRenderTargetItem& EffectiveRT = FSceneRenderTargets::Get(RHICmdList).SkySHIrradianceMap->GetRenderTargetItem(); check(EffectiveRT.ShaderResourceTexture->GetFormat() == PF_FloatRGBA); TArray<FFloat16Color> SurfaceData; RHICmdList.ReadSurfaceFloatData(EffectiveRT.ShaderResourceTexture, FIntRect(0, 0, FSHVector3::MaxSHBasis, 1), SurfaceData, CubeFace_PosX, 0, 0); check(SurfaceData.Num() == FSHVector3::MaxSHBasis); for (int32 CoefficientIndex = 0; CoefficientIndex < FSHVector3::MaxSHBasis; CoefficientIndex++) { const FLinearColor CoefficientValue(SurfaceData[CoefficientIndex]); OutIrradianceEnvironmentMap->R.V[CoefficientIndex] = CoefficientValue.R; OutIrradianceEnvironmentMap->G.V[CoefficientIndex] = CoefficientValue.G; OutIrradianceEnvironmentMap->B.V[CoefficientIndex] = CoefficientValue.B; } } }
void FEditorLiveStreaming::StartBroadcastingEditor() { if( !IsBroadcastingEditor() && IsLiveStreamingAvailable() ) { // Select a live streaming service { static const FName LiveStreamingFeatureName( "LiveStreaming" ); LiveStreamer = &IModularFeatures::Get().GetModularFeature<ILiveStreamingService>( LiveStreamingFeatureName ); } // Register to find out about status changes LiveStreamer->OnStatusChanged().AddRaw( this, &FEditorLiveStreaming::BroadcastStatusCallback ); // @todo livestream: Allow connection to chat independently from broadcasting? (see removing delegate too) LiveStreamer->OnChatMessage().AddRaw( this, &FEditorLiveStreaming::OnChatMessage ); // Tell our live streaming plugin to start broadcasting { const auto& Settings = *GetDefault< UEditorLiveStreamingSettings >(); FSlateRenderer* SlateRenderer = FSlateApplication::Get().GetRenderer().Get(); const FIntRect VirtualScreen = SlateRenderer->SetupVirtualScreenBuffer( Settings.bPrimaryMonitorOnly, Settings.ScreenScaling, LiveStreamer ); bIsBroadcasting = true; SubmittedVideoFrameCount = 0; // @todo livestream: What about if virtual screen size changes while we are still broadcasting? For example, if the user changes their // desktop resolution while the editor is running. We'd need to stop and restart the broadcast. FBroadcastConfig BroadcastConfig; BroadcastConfig.VideoBufferWidth = VirtualScreen.Width(); BroadcastConfig.VideoBufferHeight = VirtualScreen.Height(); BroadcastConfig.FramesPerSecond = Settings.FrameRate; BroadcastConfig.PixelFormat = FBroadcastConfig::EBroadcastPixelFormat::R8G8B8A8; BroadcastConfig.bCaptureAudioFromComputer = Settings.bCaptureAudioFromComputer; BroadcastConfig.bCaptureAudioFromMicrophone = Settings.bCaptureAudioFromMicrophone; LiveStreamer->StartBroadcasting( BroadcastConfig ); if( Settings.bEnableWebCam ) { FWebCamConfig WebCamConfig; switch( Settings.WebCamResolution ) { case EEditorLiveStreamingWebCamResolution::Normal_320x240: WebCamConfig.DesiredWebCamWidth = 320; WebCamConfig.DesiredWebCamHeight = 240; break; case EEditorLiveStreamingWebCamResolution::Wide_320x180: WebCamConfig.DesiredWebCamWidth = 320; WebCamConfig.DesiredWebCamHeight = 180; break; case EEditorLiveStreamingWebCamResolution::Normal_640x480: WebCamConfig.DesiredWebCamWidth = 640; WebCamConfig.DesiredWebCamHeight = 480; break; case EEditorLiveStreamingWebCamResolution::Wide_640x360: WebCamConfig.DesiredWebCamWidth = 640; WebCamConfig.DesiredWebCamHeight = 360; break; case EEditorLiveStreamingWebCamResolution::Normal_800x600: WebCamConfig.DesiredWebCamWidth = 800; WebCamConfig.DesiredWebCamHeight = 600; break; case EEditorLiveStreamingWebCamResolution::Wide_800x450: WebCamConfig.DesiredWebCamWidth = 800; WebCamConfig.DesiredWebCamHeight = 450; break; case EEditorLiveStreamingWebCamResolution::Normal_1024x768: WebCamConfig.DesiredWebCamWidth = 1024; WebCamConfig.DesiredWebCamHeight = 768; break; case EEditorLiveStreamingWebCamResolution::Wide_1024x576: WebCamConfig.DesiredWebCamWidth = 1024; WebCamConfig.DesiredWebCamHeight = 576; break; case EEditorLiveStreamingWebCamResolution::Normal_1080x810: WebCamConfig.DesiredWebCamWidth = 1080; WebCamConfig.DesiredWebCamHeight = 810; break; case EEditorLiveStreamingWebCamResolution::Wide_1080x720: WebCamConfig.DesiredWebCamWidth = 1080; WebCamConfig.DesiredWebCamHeight = 720; break; case EEditorLiveStreamingWebCamResolution::Normal_1280x960: WebCamConfig.DesiredWebCamWidth = 1280; WebCamConfig.DesiredWebCamHeight = 960; break; case EEditorLiveStreamingWebCamResolution::Wide_1280x720: WebCamConfig.DesiredWebCamWidth = 1280; WebCamConfig.DesiredWebCamHeight = 720; break; case EEditorLiveStreamingWebCamResolution::Normal_1920x1440: WebCamConfig.DesiredWebCamWidth = 1920; WebCamConfig.DesiredWebCamHeight = 1440; break; case EEditorLiveStreamingWebCamResolution::Wide_1920x1080: WebCamConfig.DesiredWebCamWidth = 1920; WebCamConfig.DesiredWebCamHeight = 1080; break; default: check(0); break; } // @todo livestream: Allow web cam to be started/stopped independently from the broadcast itself, so users can setup their web cam LiveStreamer->StartWebCam( WebCamConfig ); } } } }
void FRCPassPostProcessUpscale::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessUpscale); 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.UnscaledViewRect; FIntPoint SrcSize = InputDesc->Extent; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.SetViewportAndCallRHI(DestRect); bool bTessellatedQuad = PaniniConfig.D >= 0.01f; // with distortion (bTessellatedQuad) we need to clear the background FIntRect ExcludeRect = bTessellatedQuad ? FIntRect() : DestRect; Context.RHICmdList.Clear(true, FLinearColor::Black, false, 1.0f, false, 0, ExcludeRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); FShader* VertexShader = 0; if(bTessellatedQuad) { switch (UpscaleQuality) { case 0: VertexShader = SetShader<0, 1>(Context, PaniniConfig); break; case 1: VertexShader = SetShader<1, 1>(Context, PaniniConfig); break; case 2: VertexShader = SetShader<2, 1>(Context, PaniniConfig); break; case 3: VertexShader = SetShader<3, 1>(Context, PaniniConfig); break; default: checkNoEntry(); break; } } else { switch (UpscaleQuality) { case 0: VertexShader = SetShader<0, 0>(Context, PaniniParams::Default); break; case 1: VertexShader = SetShader<1, 0>(Context, PaniniParams::Default); break; case 2: VertexShader = SetShader<2, 0>(Context, PaniniParams::Default); break; case 3: VertexShader = SetShader<3, 0>(Context, PaniniParams::Default); break; default: checkNoEntry(); break; } } // Draw a quad, a triangle or a tessellated quad DrawRectangle( Context.RHICmdList, 0, 0, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestRect.Size(), SrcSize, VertexShader, bTessellatedQuad ? EDRF_UseTesselatedIndexBuffer: EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessSelectionOutline::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSelectionOutline); const FPooledRenderTargetDesc* SceneColorInputDesc = GetInputDesc(ePId_Input0); const FPooledRenderTargetDesc* SelectionColorInputDesc = GetInputDesc(ePId_Input1); if (!SceneColorInputDesc || !SelectionColorInputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; FIntRect ViewRect = View.ViewRect; FIntPoint SrcSize = SceneColorInputDesc->Extent; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); Context.RHICmdList.Clear(true, FLinearColor::Black, false, (float)ERHIZBuffer::FarPlane, false, 0, ViewRect); Context.SetViewportAndCallRHI(ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); const uint32 MSAASampleCount = FSceneRenderTargets::Get(Context.RHICmdList).GetEditorMSAACompositingSampleCount(); if(MSAASampleCount == 1) { SetSelectionOutlineShaderTempl<1>(Context); } else if(MSAASampleCount == 2) { SetSelectionOutlineShaderTempl<2>(Context); } else if(MSAASampleCount == 4) { SetSelectionOutlineShaderTempl<4>(Context); } else if(MSAASampleCount == 8) { SetSelectionOutlineShaderTempl<8>(Context); } else { // not supported, internal error check(0); } // Draw a quad mapping scene color to the view's render target TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); DrawRectangle( Context.RHICmdList, 0, 0, ViewRect.Width(), ViewRect.Height(), ViewRect.Min.X, ViewRect.Min.Y, ViewRect.Width(), ViewRect.Height(), ViewRect.Size(), SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessBloomSetup::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(PostProcessBloomSetup, 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); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect; const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); // Set the view family's render target/viewport. RHISetRenderTarget(DestRenderTarget.TargetableTexture, FTextureRHIRef()); // is optimized away if possible (RT size=view size, ) RHIClear(true, FLinearColor::Black, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessBloomSetupVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FPostProcessBloomSetupPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetVS(Context); PixelShader->SetPS(Context); // Draw a quad mapping scene color to the view's render target DrawRectangle( DestRect.Min.X, DestRect.Min.Y, DestRect.Width(), DestRect.Height(), SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width(), SrcRect.Height(), DestSize, SrcSize, EDRF_UseTriangleOptimization); RHICopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FVoronoiDiagramSite::GenerateCentroid(FIntRect Bounds) { TArray<FVector2D> SortedVertices; // Gather all vertices from the edges // Solve for corners bool bHas_X_Min = false; bool bHas_X_Max = false; bool bHas_Min_Y = false; bool bHas_Max_Y = false; for(auto Itr(Edges.CreateConstIterator()); Itr; ++Itr) { TSharedPtr<FVoronoiDiagramEdge, ESPMode::ThreadSafe> CurrentEdge = (*Itr); // Don't add edge that is (0,0) -> (0,0). Increment Index if no edge is removed, otherwise the remove should do this shifting for us if( FMath::IsNearlyEqual(CurrentEdge->LeftClippedEndPoint.X, FLT_MIN) && FMath::IsNearlyEqual(CurrentEdge->LeftClippedEndPoint.Y, FLT_MIN) && FMath::IsNearlyEqual(CurrentEdge->RightClippedEndPoint.X, FLT_MIN) && FMath::IsNearlyEqual(CurrentEdge->RightClippedEndPoint.Y, FLT_MIN) ) { continue; } FVector2D LeftEndPoint = CurrentEdge->LeftClippedEndPoint; FVector2D RightEndPoint = CurrentEdge->RightClippedEndPoint; // (x, Min) if(FMath::IsNearlyZero(LeftEndPoint.Y, NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyZero(RightEndPoint.Y, NOT_REALLY_KINDA_SMALL_NUMBER)) { bHas_X_Min = true; } // (x, Max) if(FMath::IsNearlyEqual(LeftEndPoint.Y, Bounds.Height(), NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyEqual(RightEndPoint.Y, Bounds.Height(), NOT_REALLY_KINDA_SMALL_NUMBER)) { bHas_X_Max = true; } // (Min, y) if(FMath::IsNearlyZero(LeftEndPoint.X, NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyZero(RightEndPoint.X, NOT_REALLY_KINDA_SMALL_NUMBER)) { bHas_Min_Y = true; } // (Max, y) if(FMath::IsNearlyEqual(LeftEndPoint.X, Bounds.Width(), NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyEqual(RightEndPoint.X, Bounds.Width(), NOT_REALLY_KINDA_SMALL_NUMBER)) { bHas_Max_Y = true; } SortedVertices.Add(LeftEndPoint); SortedVertices.Add(RightEndPoint); } // Add corners if applicable // (x, Min) -> (Min, y) // Min, Min Corner if(bHas_X_Min && bHas_Min_Y) { SortedVertices.Add(FVector2D(0.0f, 0.0f)); bIsCorner = true; } // x, Min -> Max, y // Min, Max Corner if(bHas_X_Min && bHas_Max_Y) { SortedVertices.Add(FVector2D(Bounds.Width(), 0.0f)); bIsCorner = true; } // x, Max -> Min, y // Max, Min Corner if(bHas_X_Max && bHas_Min_Y) { SortedVertices.Add(FVector2D(0.0f, static_cast<float>(Bounds.Height()))); bIsCorner = true; } // x, Max -> Max, y // Max, Max Corner if(bHas_X_Max && bHas_Max_Y) { SortedVertices.Add(FVector2D(static_cast<float>(Bounds.Width()), static_cast<float>(Bounds.Height()))); bIsCorner = true; } if(bHas_X_Min || bHas_X_Max || bHas_Min_Y || bHas_Max_Y) { bIsEdge = true; } // Monotone Chain // Sort the vertices lexigraphically by X and then Y struct FSortVertex { bool operator()(const FVector2D& A, const FVector2D& B) const { if(A.X < B.X) { return true; } if(A.X > B.X) { return false; } if(A.Y < B.Y) { return true; } if(A.Y > B.Y) { return false; } return false; } }; SortedVertices.Sort(FSortVertex()); TArray<FVector2D> LowerHull; for(int32 i = 0; i < SortedVertices.Num(); ++i) { while(LowerHull.Num() >= 2 && (Cross( LowerHull[ LowerHull.Num() - 2 ], LowerHull[ LowerHull.Num() - 1 ], SortedVertices[i]) < 0.0f || FMath::IsNearlyZero(Cross( LowerHull[ LowerHull.Num() - 2 ], LowerHull[ LowerHull.Num() - 1 ], SortedVertices[i])))) { LowerHull.RemoveAt(LowerHull.Num() - 1); } LowerHull.Add(SortedVertices[i]); } TArray<FVector2D> UpperHull; for(int32 i = SortedVertices.Num() - 1; i >= 0; --i) { while(UpperHull.Num() >= 2 && (Cross( UpperHull[ UpperHull.Num() - 2 ], UpperHull[ UpperHull.Num() - 1 ], SortedVertices[i]) < 0.0f || FMath::IsNearlyZero(Cross( UpperHull[ UpperHull.Num() - 2 ], UpperHull[ UpperHull.Num() - 1 ], SortedVertices[i])))) { UpperHull.RemoveAt(UpperHull.Num() - 1); } UpperHull.Add(SortedVertices[i]); } // Remove last point because they are represented in the other list UpperHull.RemoveAt(UpperHull.Num() - 1); LowerHull.RemoveAt(LowerHull.Num() - 1); SortedVertices.Empty(); SortedVertices.Append(LowerHull); SortedVertices.Append(UpperHull); // Calculate Centroid Centroid = FVector2D::ZeroVector; Vertices.Empty(); Vertices.Append(SortedVertices); FVector2D CurrentVertex; FVector2D NextVertex; float SignedArea = 0.0f; float PartialArea; // Use all vertices except the last one for(int32 Index = 0; Index < SortedVertices.Num() - 1; ++Index) { CurrentVertex = FVector2D(SortedVertices[Index]); NextVertex = FVector2D(SortedVertices[Index + 1]); PartialArea = CurrentVertex.X * NextVertex.Y - NextVertex.X * CurrentVertex.Y; SignedArea += PartialArea; Centroid = FVector2D(Centroid.X + (CurrentVertex.X + NextVertex.X) * PartialArea, Centroid.Y + (CurrentVertex.Y + NextVertex.Y) * PartialArea); } // Process last vertex CurrentVertex = SortedVertices[SortedVertices.Num() - 1]; NextVertex = SortedVertices[0]; PartialArea = (CurrentVertex.X * NextVertex.Y - NextVertex.X * CurrentVertex.Y); SignedArea += PartialArea; Centroid = FVector2D(Centroid.X + (CurrentVertex.X + NextVertex.X) * PartialArea, Centroid.Y + (CurrentVertex.Y + NextVertex.Y) * PartialArea); SignedArea *= 0.5f; Centroid = FVector2D( Centroid.X / (6.0f * SignedArea), Centroid.Y / (6.0f * SignedArea) ); // UE_LOG(LogVoronoiDiagram, Log, TEXT("Centroid (%f, %f)"), Centroid.X, Centroid.Y); // if(Centroid.X == NAN || Centroid.Y == NAN) // { // UE_LOG(LogVoronoiDiagram, Log, TEXT("Centroid (%f, %f)"), Centroid.X, Centroid.Y); // for(auto Itr(SortedVertices.CreateConstIterator()); Itr; ++Itr) // { // UE_LOG(LogVoronoiDiagram, Log, TEXT("Vertex (%f, %f)"), (*Itr).X, (*Itr).Y); // } // } }
void FVisualizeTexture::PresentContent(const FSceneView& View) { if(Mode != 0) { // old mode is used, lets copy the specified texture to do it similar to the new system FPooledRenderTarget* Element = GRenderTargetPool.GetElementById(Mode - 1); if(Element) { GenerateContent(Element->GetRenderTargetItem(), Element->GetDesc()); } } const FTexture2DRHIRef& RenderTargetTexture = View.Family->RenderTarget->GetRenderTargetTexture(); if(!VisualizeTextureContent || !IsValidRef(RenderTargetTexture) || GRHIFeatureLevel < ERHIFeatureLevel::SM3) { // visualize feature is deactivated return; } FPooledRenderTargetDesc Desc = VisualizeTextureDesc; RHISetRenderTarget(View.Family->RenderTarget->GetRenderTargetTexture(),FTextureRHIRef()); RHISetViewport(0, 0, 0.0f, GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y, 1.0f ); RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(GetGlobalShaderMap()); TShaderMapRef<FVisualizeTexturePresentPS> PixelShader(GetGlobalShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetParameters(View); PixelShader->SetParameters(View, *VisualizeTextureContent); FIntRect DestRect = View.ViewRect; FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent); // Draw a quad mapping scene color to the view's render target DrawRectangle( VisualizeTextureRect.Min.X, VisualizeTextureRect.Min.Y, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), 0, 0, VisualizeTextureRect.Width(), VisualizeTextureRect.Height(), GSceneRenderTargets.GetBufferSizeXY(), VisualizeTextureRect.Size(), EDRF_Default); // this is a helper class for FCanvas to be able to get screen size class FRenderTargetTemp : public FRenderTarget { public: const FSceneView& View; FRenderTargetTemp(const FSceneView& InView) : View(InView) { } virtual FIntPoint GetSizeXY() const { return View.UnscaledViewRect.Size(); }; virtual const FTexture2DRHIRef& GetRenderTargetTexture() const { return View.Family->RenderTarget->GetRenderTargetTexture(); } } TempRenderTarget(View); FCanvas Canvas(&TempRenderTarget, NULL, View.Family->CurrentRealTime, View.Family->CurrentWorldTime, View.Family->DeltaWorldTime); float X = 100 + View.ViewRect.Min.X; float Y = 160 + View.ViewRect.Min.Y; float YStep = 14; { uint32 ReuseCount = ObservedDebugNameReusedCurrent; FString ExtendedName; if(ReuseCount) { uint32 ReuseGoal = FMath::Min(ReuseCount - 1, ObservedDebugNameReusedGoal); // was reused this frame ExtendedName = FString::Printf(TEXT("%s@%d @0..%d"), Desc.DebugName, ReuseGoal, ReuseCount - 1); } else { // was not reused this frame but can be referenced ExtendedName = FString::Printf(TEXT("%s"), Desc.DebugName); } FString Line = FString::Printf(TEXT("VisualizeTexture: %d \"%s\" RGB*%g+A*%g UV%d"), Mode, *ExtendedName, RGBMul, AMul, UVInputMapping); Canvas.DrawShadowedString( X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" TextureInfoString(): %s"), *(Desc.GenerateInfoString())); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } { FString Line = FString::Printf(TEXT(" BufferSize:(%d,%d)"), GSceneRenderTargets.GetBufferSizeXY().X, GSceneRenderTargets.GetBufferSizeXY().Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } const FSceneViewFamily& ViewFamily = *View.Family; for(int32 ViewId = 0; ViewId < ViewFamily.Views.Num(); ++ViewId) { const FSceneView& ViewIt = *ViewFamily.Views[ViewId]; FString Line = FString::Printf(TEXT(" View #%d: (%d,%d)-(%d,%d)"), ViewId + 1, ViewIt.ViewRect.Min.X, ViewIt.ViewRect.Min.Y, ViewIt.ViewRect.Max.X, ViewIt.ViewRect.Max.Y); Canvas.DrawShadowedString( X + 10, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1)); } X += 40; Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Red: <0"), GetStatsFont(), FLinearColor(1,0,0)); Canvas.DrawShadowedString( X, Y += YStep, TEXT("Blinking Blue: NAN or Inf"), GetStatsFont(), FLinearColor(0,0,1)); Canvas.Flush(); }
/** * If any of the active subtitles need to be split into multiple lines, do so now * - caveat - this assumes the width of the subtitle region does not change while the subtitle is active */ void FSubtitleManager::SplitLinesToSafeZone( FCanvas* Canvas, FIntRect& SubtitleRegion ) { int32 i; FString Concatenated; float SoundDuration; float StartTime, SecondsPerChar, Cumulative; for( TMap<PTRINT, FActiveSubtitle>::TIterator It( ActiveSubtitles ); It; ++It ) { FActiveSubtitle& Subtitle = It.Value(); if( Subtitle.bSplit ) { continue; } // Concatenate the lines into one (in case the lines were partially manually split) Concatenated.Empty( 256 ); // Set up the base data FSubtitleCue& Initial = Subtitle.Subtitles[ 0 ]; Concatenated = Initial.Text.ToString(); StartTime = Initial.Time; SoundDuration = 0.0f; for( i = 1; i < Subtitle.Subtitles.Num(); i++ ) { FSubtitleCue& Subsequent = Subtitle.Subtitles[ i ]; Concatenated += Subsequent.Text.ToString(); // Last blank entry sets the cutoff time to the duration of the sound SoundDuration = Subsequent.Time - StartTime; } // Adjust concat string to use \n character instead of "/n" or "\n" int32 SubIdx = Concatenated.Find( TEXT( "/n" ) ); while( SubIdx >= 0 ) { Concatenated = Concatenated.Left( SubIdx ) + ( ( TCHAR )L'\n' ) + Concatenated.Right( Concatenated.Len() - ( SubIdx + 2 ) ); SubIdx = Concatenated.Find( TEXT( "/n" ) ); } SubIdx = Concatenated.Find( TEXT( "\\n" ) ); while( SubIdx >= 0 ) { Concatenated = Concatenated.Left( SubIdx ) + ( ( TCHAR )L'\n' ) + Concatenated.Right( Concatenated.Len() - ( SubIdx + 2 ) ); SubIdx = Concatenated.Find( TEXT( "\\n" )); } // Work out a metric for the length of time a line should be displayed SecondsPerChar = SoundDuration / Concatenated.Len(); // Word wrap into lines TArray<FWrappedStringElement> Lines; FTextSizingParameters RenderParms( 0.0f, 0.0f, SubtitleRegion.Width(), 0.0f, GEngine->GetSubtitleFont() ); Canvas->WrapString( RenderParms, 0, *Concatenated, Lines ); // Set up the times Subtitle.Subtitles.Empty(); Cumulative = 0.0f; for( i = 0; i < Lines.Num(); i++ ) { FSubtitleCue* Line = new( Subtitle.Subtitles ) FSubtitleCue(); Line->Text = FText::FromString(Lines[ i ].Value); Line->Time = StartTime + Cumulative; Cumulative += SecondsPerChar * Line->Text.ToString().Len(); } // Add in the blank terminating line FSubtitleCue* Temp = new( Subtitle.Subtitles ) FSubtitleCue(); Temp->Text = FText::GetEmpty(); Temp->Time = StartTime + SoundDuration; UE_LOG(LogAudio, Log, TEXT( "Splitting subtitle:" ) ); for( i = 0; i < Subtitle.Subtitles.Num() - 1; i++ ) { FSubtitleCue& Cue = Subtitle.Subtitles[ i ]; FSubtitleCue& NextCue = Subtitle.Subtitles[ i + 1 ]; UE_LOG(LogAudio, Log, TEXT( " ... '%s' at %g to %g" ), *(Cue.Text.ToString()), Cue.Time, NextCue.Time ); } // Mark it as split so it doesn't happen again Subtitle.bSplit = true; } }
void FRCPassPostProcessCircleDOFDilate::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, CircleDOFNear); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } uint32 NumRenderTargets = 1; const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); const auto FeatureLevel = Context.GetFeatureLevel(); auto ShaderMap = Context.GetShaderMap(); FIntPoint SrcSize = InputDesc->Extent; FIntPoint DestSize = PassOutputs[0].RenderTargetDesc.Extent; // e.g. 4 means the input texture is 4x smaller than the buffer size uint32 ScaleFactor = GSceneRenderTargets.GetBufferSizeXY().X / SrcSize.X; FIntRect SrcRect = View.ViewRect / ScaleFactor; FIntRect DestRect = SrcRect / 2; const FSceneRenderTargetItem& DestRenderTarget0 = PassOutputs[0].RequestSurface(Context); const FSceneRenderTargetItem& DestRenderTarget1 = FSceneRenderTargetItem(); // Set the view family's render target/viewport. FTextureRHIParamRef RenderTargets[2] = { DestRenderTarget0.TargetableTexture, DestRenderTarget1.TargetableTexture }; SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, FTextureRHIParamRef(), 0, NULL); FLinearColor ClearColors[2] = { FLinearColor(0, 0, 0, 0), FLinearColor(0, 0, 0, 0) }; // is optimized away if possible (RT size=view size, ) Context.RHICmdList.ClearMRT(true, NumRenderTargets, ClearColors, false, 1.0f, false, 0, DestRect); Context.SetViewportAndCallRHI(0, 0, 0.0f, DestSize.X, DestSize.Y, 1.0f ); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(ShaderMap); if (false) { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessCircleDOFDilatePS<1> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } else { static FGlobalBoundShaderState BoundShaderState; TShaderMapRef< FPostProcessCircleDOFDilatePS<0> > PixelShader(ShaderMap); SetGlobalBoundShaderState(Context.RHICmdList, FeatureLevel, BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(Context); } VertexShader->SetParameters(Context); // Draw a quad mapping scene color to the view's render target DrawRectangle( Context.RHICmdList, DestRect.Min.X, DestRect.Min.Y, DestRect.Width() + 1, DestRect.Height() + 1, SrcRect.Min.X, SrcRect.Min.Y, SrcRect.Width() + 1, SrcRect.Height() + 1, DestSize, SrcSize, *VertexShader, EDRF_UseTriangleOptimization); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget0.TargetableTexture, DestRenderTarget0.ShaderResourceTexture, false, FResolveParams()); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget1.TargetableTexture, DestRenderTarget1.ShaderResourceTexture, false, FResolveParams()); }
void FCrashVideoCapture::Update(float DeltaSeconds) { SCOPE_CYCLE_COUNTER(STAT_TotalTime); if (bIsRunning) { // Update the key press buffer times for (int32 i = 0; i < KeypressBuffer.Num(); ++i) { KeypressBuffer[i].Value -= DeltaSeconds; } // check to see if we need to render a new frame bool bShouldUpdate = false; CurrentAccumSeconds += DeltaSeconds; if (CurrentAccumSeconds > CrashTrackerConstants::CaptureFrequency) { CurrentAccumSeconds -= FMath::TruncToFloat(CurrentAccumSeconds / CrashTrackerConstants::CaptureFrequency) * CrashTrackerConstants::CaptureFrequency; bShouldUpdate = true; } if (bShouldUpdate) { CleanupKeyPressBuffer(DeltaSeconds); TArray<FString> StrippedKeyPressBuffer; for (int32 i = 0; i < KeypressBuffer.Num(); ++i) { StrippedKeyPressBuffer.Add(KeypressBuffer[i].Key); } const FMappedTextureBuffer& CurrentBuffer = Buffer[CurrentBufferIndex]; if ( CurrentBuffer.IsValid() ) { IImageWrapperPtr ImageWrapper; { SCOPE_CYCLE_COUNTER(STAT_SendFrameToCompressor); IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>( FName("ImageWrapper") ); ImageWrapper = ImageWrapperModule.CreateImageWrapper( EImageFormat::JPEG ); ImageWrapper->SetRaw(CurrentBuffer.Data, CurrentBuffer.Width * CurrentBuffer.Height * sizeof(FColor), CurrentBuffer.Width, CurrentBuffer.Height, ERGBFormat::RGBA, 8); } { SCOPE_CYCLE_COUNTER(STAT_WaitForPreviousFrameToCompress); SyncWorkerThread(); AsyncTask = new FAsyncTask<class FAsyncImageCompress>(ImageWrapper, CompressedFrames[CurrentFrameCaptureIndex]); AsyncTask->StartBackgroundTask(); } CaptureSlateRenderer->UnmapVirtualScreenBuffer(); } ++CurrentFrameCaptureIndex; if (CurrentFrameCaptureIndex >= CrashTrackerConstants::VideoFramesToCapture) { CurrentFrameCaptureIndex = 0; } const bool bPrimaryWorkAreaOnly = false; // We want all monitors captured for crash reporting const FIntRect VirtualScreen = CaptureSlateRenderer->SetupVirtualScreenBuffer(bPrimaryWorkAreaOnly, CrashTrackerConstants::ScreenScaling, nullptr); Width = VirtualScreen.Width(); Height = VirtualScreen.Height(); CaptureSlateRenderer->CopyWindowsToVirtualScreenBuffer(StrippedKeyPressBuffer); CaptureSlateRenderer->MapVirtualScreenBuffer(&Buffer[CurrentBufferIndex]); CurrentBufferIndex = (CurrentBufferIndex + 1) % 2; } } }