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 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 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 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()); }