void FVisualizeTexture::GenerateContent(const FSceneRenderTargetItem& RenderTargetItem, const FPooledRenderTargetDesc& Desc) { // otherwise StartFrame() wasn't called check(ViewRect != FIntRect(0, 0, 0, 0)) FTexture2DRHIRef VisTexture = (FTexture2DRHIRef&)RenderTargetItem.ShaderResourceTexture; if(!IsValidRef(VisTexture) || !Desc.IsValid()) { // todo: improve return; } FIntRect VisualizeTextureRect = ComputeVisualizeTextureRect(Desc.Extent); FIntPoint Size = VisualizeTextureRect.Size(); // clamp to reasonable value to prevent crash Size.X = FMath::Max(Size.X, 1); Size.Y = FMath::Max(Size.Y, 1); FPooledRenderTargetDesc OutputDesc(FPooledRenderTargetDesc::Create2DDesc(Size, PF_B8G8R8A8, TexCreate_None, TexCreate_RenderTargetable | TexCreate_ShaderResource, false)); GRenderTargetPool.FindFreeElement(OutputDesc, VisualizeTextureContent, TEXT("VisualizeTexture")); if(!VisualizeTextureContent) { return; } const FSceneRenderTargetItem& DestRenderTarget = VisualizeTextureContent->GetRenderTargetItem(); RHISetRenderTarget(DestRenderTarget.TargetableTexture, FTextureRHIRef()); RHIClear(true, FLinearColor(1,1,0,1), false, 0.0f, false, 0, FIntRect()); RHISetBlendState(TStaticBlendState<>::GetRHI()); RHISetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHISetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); FIntPoint RTExtent = GSceneRenderTargets.GetBufferSizeXY(); FVector2D Tex00 = FVector2D(0, 0); FVector2D Tex11 = FVector2D(1, 1); uint32 LocalVisualizeTextureInputMapping = UVInputMapping; if(!Desc.Is2DTexture()) { LocalVisualizeTextureInputMapping = 1; } // set UV switch(LocalVisualizeTextureInputMapping) { // UV in left top case 0: Tex11 = FVector2D((float)ViewRect.Width() / RTExtent.X, (float)ViewRect.Height() / RTExtent.Y); break; // whole texture default: break; } bool bIsDefault = StencilSRVSrc == GBlackTexture->TextureRHI; bool bDepthStencil = Desc.Is2DTexture() && Desc.Format == PF_DepthStencil; //clear if this is a new different Stencil buffer, or it's not a stencil buffer and we haven't switched to the default yet. bool bNeedsClear = bDepthStencil && (StencilSRVSrc != RenderTargetItem.TargetableTexture); bNeedsClear |= !bDepthStencil && !bIsDefault; if (bNeedsClear) { StencilSRVSrc = nullptr; StencilSRV.SafeRelease(); } //always set something into the StencilSRV slot for platforms that require a full resource binding, even if //dynamic branching will cause them not to be used. if(bDepthStencil && !StencilSRVSrc) { StencilSRVSrc = RenderTargetItem.TargetableTexture; StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) RenderTargetItem.TargetableTexture, 0, 1, PF_X24_G8); } else if(!StencilSRVSrc) { StencilSRVSrc = GBlackTexture->TextureRHI; StencilSRV = RHICreateShaderResourceView((FTexture2DRHIRef&) GBlackTexture->TextureRHI, 0, 1, PF_B8G8R8A8); } FVisualizeTextureData VisualizeTextureData(RenderTargetItem, Desc); bool bDepthTexture = (Desc.TargetableFlags & TexCreate_DepthStencilTargetable) != 0; VisualizeTextureData.RGBMul = RGBMul; VisualizeTextureData.AMul = AMul; VisualizeTextureData.Tex00 = Tex00; VisualizeTextureData.Tex11 = Tex11; VisualizeTextureData.bSaturateInsteadOfFrac = (Flags & 1) != 0; VisualizeTextureData.InputValueMapping = bDepthTexture ? 1 : 0; VisualizeTextureData.ArrayIndex = ArrayIndex; VisualizeTextureData.CustomMip = CustomMip; VisualizeTextureData.StencilSRV = StencilSRV; { SCOPED_DRAW_EVENT(VisualizeTexture, DEC_SCENE_ITEMS); // continue rendering to HDR if necessary RenderVisualizeTexture(VisualizeTextureData); } RHICopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); VisualizeTextureDesc = Desc; // save to disk if(bSaveBitmap) { bSaveBitmap = false; uint32 MipAdjustedExtentX = FMath::Clamp(Desc.Extent.X >> CustomMip, 0, Desc.Extent.X); uint32 MipAdjustedExtentY = FMath::Clamp(Desc.Extent.Y >> CustomMip, 0, Desc.Extent.Y); FIntPoint Extent(MipAdjustedExtentX, MipAdjustedExtentY); FReadSurfaceDataFlags ReadDataFlags; ReadDataFlags.SetLinearToGamma(false); ReadDataFlags.SetOutputStencil(bOutputStencil); ReadDataFlags.SetMip(CustomMip); FTextureRHIRef Texture = RenderTargetItem.TargetableTexture ? RenderTargetItem.TargetableTexture : RenderTargetItem.ShaderResourceTexture; check(Texture); TArray<FColor> Bitmap; RHIReadSurfaceData(Texture, FIntRect(0, 0, Extent.X, Extent.Y), Bitmap, ReadDataFlags); // if the format and texture type is supported if(Bitmap.Num()) { // Create screenshot folder if not already present. IFileManager::Get().MakeDirectory(*FPaths::ScreenShotDir(), true); const FString ScreenFileName(FPaths::ScreenShotDir() / TEXT("VisualizeTexture")); uint32 ExtendXWithMSAA = Bitmap.Num() / Extent.Y; // Save the contents of the array to a bitmap file. (24bit only so alpha channel is dropped) FFileHelper::CreateBitmap(*ScreenFileName, ExtendXWithMSAA, Extent.Y, Bitmap.GetTypedData()); UE_LOG(LogConsoleResponse, Display, TEXT("Content was saved to \"%s\""), *FPaths::ScreenShotDir()); } else { UE_LOG(LogConsoleResponse, Error, TEXT("Failed to save BMP for VisualizeTexture, format or texture type is not supported")); } } }
void FRCPassPostProcessLpvIndirect::Process(FRenderingCompositePassContext& Context) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(Context.RHICmdList); { FRenderingCompositeOutput* OutputOfMyInput = GetInput(ePId_Input0)->GetOutput(); PassOutputs[0].PooledRenderTarget = OutputOfMyInput->PooledRenderTarget; OutputOfMyInput->RenderTargetDesc.DebugName = PassOutputs[0].RenderTargetDesc.DebugName; PassOutputs[0].RenderTargetDesc = OutputOfMyInput->RenderTargetDesc; check(PassOutputs[0].RenderTargetDesc.Extent.X); check(PassOutputs[0].RenderTargetDesc.Extent.Y); } const FFinalPostProcessSettings& PostprocessSettings = Context.View.FinalPostProcessSettings; const FSceneView& View = Context.View; FSceneViewState* ViewState = (FSceneViewState*)View.State; if(!ViewState) { return; } // This check should be inclusive to stereo views const bool bIncludeStereoViews = true; FLightPropagationVolume* Lpv = ViewState->GetLightPropagationVolume(Context.GetFeatureLevel(), bIncludeStereoViews); const FLightPropagationVolumeSettings& LPVSettings = PostprocessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); if(!Lpv || LPVSettings.LPVIntensity == 0.0f) { return; } const FSceneViewFamily& ViewFamily = *(View.Family); FIntRect SrcRect = View.ViewRect; // todo: view size should scale with input texture size so we can do SSAO in half resolution as well FIntRect DestRect = View.ViewRect; FIntPoint DestSize = DestRect.Size(); const bool bMixing = CVarLPVMixing.GetValueOnRenderThread() != 0; // Apply specular separately if we're mixing reflection environment with indirect lighting const bool bApplySeparateSpecularRT = View.Family->EngineShowFlags.ReflectionEnvironment && bMixing; const FSceneRenderTargetItem& DestColorRenderTarget = SceneContext.GetSceneColor()->GetRenderTargetItem(); const FSceneRenderTargetItem& DestSpecularRenderTarget = SceneContext.LightAccumulation->GetRenderTargetItem(); const FSceneRenderTargetItem& DestDirectionalOcclusionRenderTarget = SceneContext.DirectionalOcclusion->GetRenderTargetItem(); // Make sure the LPV Update has completed Lpv->InsertGPUWaitForAsyncUpdate(Context.RHICmdList); if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { DoDirectionalOcclusionPass(Context); } FTextureRHIParamRef RenderTargets[2]; RenderTargets[0] = DestColorRenderTarget.TargetableTexture; RenderTargets[1] = DestSpecularRenderTarget.TargetableTexture; // Set the view family's render target/viewport. // If specular not applied: set only color target uint32 NumRenderTargets = 1; if ( bApplySeparateSpecularRT ) { NumRenderTargets = 2; } SetRenderTargets(Context.RHICmdList, NumRenderTargets, RenderTargets, 0, ESimpleRenderTargetMode::EExistingColorAndDepth, FExclusiveDepthStencil::DepthRead_StencilNop); Context.SetViewportAndCallRHI(View.ViewRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGB,BO_Add,BF_One,BF_One,BO_Add,BF_One,BF_One>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<false> > PixelShaderNoSpecular(Context.GetShaderMap()); TShaderMapRef< TPostProcessLpvIndirectPS<true> > PixelShaderWithSpecular(Context.GetShaderMap()); FPostProcessLpvIndirectPS* PixelShader = NULL; int BoundShaderIndex = -1; if ( bApplySeparateSpecularRT ) { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderWithSpecular; BoundShaderIndex = 0; } else { PixelShader = (FPostProcessLpvIndirectPS*)*PixelShaderNoSpecular; BoundShaderIndex = 1; } static FGlobalBoundShaderState BoundShaderState[2]; // call it once after setting up the shader data to avoid the warnings in the function SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState[BoundShaderIndex], GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, PixelShader); FLpvReadUniformBufferParameters LpvReadUniformBufferParams; FLpvReadUniformBufferRef LpvReadUniformBuffer; LpvReadUniformBufferParams = Lpv->GetReadUniformBufferParams(); LpvReadUniformBuffer = FLpvReadUniformBufferRef::CreateUniformBufferImmediate( LpvReadUniformBufferParams, UniformBuffer_SingleDraw ); FTextureRHIParamRef LpvBufferSrvs[7]; for ( int i = 0; i < 7; i++ ) { LpvBufferSrvs[i] = Lpv->GetLpvBufferSrv(i); } PixelShader->SetParameters( LpvBufferSrvs, Lpv->GetAOVolumeTextureSRV(), LpvReadUniformBuffer, Context ); { SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessLpvIndirect ); DrawPostProcessPass( Context.RHICmdList, 0, 0, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), View.ViewRect.Size(), SceneContext.GetBufferSizeXY(), *VertexShader, View.StereoPass, Context.HasHmdMesh()); Context.RHICmdList.CopyToResolveTarget(DestColorRenderTarget.TargetableTexture, DestColorRenderTarget.ShaderResourceTexture, false, FResolveParams()); if(bApplySeparateSpecularRT) { Context.RHICmdList.CopyToResolveTarget(DestSpecularRenderTarget.TargetableTexture, DestSpecularRenderTarget.ShaderResourceTexture, false, FResolveParams()); } } if ( LPVSettings.LPVDirectionalOcclusionIntensity > 0.0001f ) { GRenderTargetPool.VisualizeTexture.SetCheckPoint(Context.RHICmdList, SceneContext.DirectionalOcclusion); } }
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 FRCPassPostProcessMotionBlurRecombine::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, MotionBlurRecombine); 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 = 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()); TShaderMapRef<FPostProcessVS> VertexShader(Context.GetShaderMap()); TShaderMapRef<FPostProcessMotionBlurRecombinePS> PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); VertexShader->SetParameters(Context); PixelShader->SetParameters(Context); // 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 FRCPassPostProcessVelocityScatter::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PassPostProcessVelocityScatter); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; 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); TRefCountPtr<IPooledRenderTarget> DepthTarget; FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( DestRect.Size(), PF_ShadowDepth, TexCreate_None, TexCreate_DepthStencilTargetable, false ) ); GRenderTargetPool.FindFreeElement( Desc, DepthTarget, TEXT("VelocityScatterDepth") ); // Set the view family's render target/viewport. SetRenderTarget( Context.RHICmdList, DestRenderTarget.TargetableTexture, DepthTarget->GetRenderTargetItem().TargetableTexture ); Context.RHICmdList.Clear( true, FLinearColor::Black, true, 0.0f, false, 0, FIntRect() ); Context.SetViewportAndCallRHI(SrcRect); // set the state Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<true, CF_Greater>::GetRHI()); TShaderMapRef< FPostProcessVelocityScatterVS > VertexShader(Context.GetShaderMap()); TShaderMapRef< FPostProcessVelocityScatterPS > PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); FIntPoint TileCount = SrcRect.Size(); VertexShader->SetParameters( Context, TileCount ); PixelShader->SetParameters( Context ); // needs to be the same on shader side (faster on NVIDIA and AMD) int32 QuadsPerInstance = 8; Context.RHICmdList.SetStreamSource(0, NULL, 0, 0); Context.RHICmdList.DrawIndexedPrimitive(GScatterQuadIndexBuffer.IndexBufferRHI, PT_TriangleList, 0, 0, 32, 0, 2 * QuadsPerInstance, FMath::DivideAndRoundUp(TileCount.X * TileCount.Y, QuadsPerInstance)); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void FRCPassPostProcessLensBlur::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, PassPostProcessLensBlur, DEC_SCENE_ITEMS); const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0); if(!InputDesc) { // input is not hooked up correctly return; } const FSceneView& View = Context.View; FIntPoint TexSize = InputDesc->Extent; // usually 1, 2, 4 or 8 uint32 ScaleToFullRes = GSceneRenderTargets.GetBufferSizeXY().X / TexSize.X; FIntRect ViewRect = FIntRect::DivideAndRoundUp(View.ViewRect, ScaleToFullRes); FIntPoint ViewSize = ViewRect.Size(); 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, 1.0f, false, 0, FIntRect()); Context.SetViewportAndCallRHI(ViewRect); // set the state (additive blending) Context.RHICmdList.SetBlendState(TStaticBlendState<CW_RGB, BO_Add, BF_One, BF_One>::GetRHI()); Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); TShaderMapRef<FPostProcessLensBlurVS> VertexShader(Context.GetShaderMap()); TShaderMapRef<FPostProcessLensBlurPS> PixelShader(Context.GetShaderMap()); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); uint32 TileSize = 1; FIntPoint TileCount = ViewSize / TileSize; float PixelKernelSize = PercentKernelSize / 100.0f * ViewSize.X; VertexShader->SetParameters(Context, TileCount, TileSize, PixelKernelSize, Threshold); PixelShader->SetParameters(Context, PixelKernelSize); Context.RHICmdList.SetStreamSource(0, NULL, 0, 0); // needs to be the same on shader side (faster on NVIDIA and AMD) int32 QuadsPerInstance = 4; Context.RHICmdList.DrawPrimitive(PT_TriangleList, 0, 2, FMath::DivideAndRoundUp(TileCount.X * TileCount.Y, QuadsPerInstance)); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
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 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 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()); }