void AllocateOrReuseLightShaftRenderTarget(FRHICommandListImmediate& RHICmdList, TRefCountPtr<IPooledRenderTarget>& Target, const TCHAR* Name) { if (!Target) { EPixelFormat LightShaftFilterBufferFormat = PF_FloatRGB; const FIntPoint BufferSize = FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY(); FIntPoint LightShaftSize(FMath::Max<uint32>(BufferSize.X / GetLightShaftDownsampleFactor(), 1), FMath::Max<uint32>(BufferSize.Y / GetLightShaftDownsampleFactor(), 1)); FPooledRenderTargetDesc Desc(FPooledRenderTargetDesc::Create2DDesc(LightShaftSize, LightShaftFilterBufferFormat, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable, false)); GRenderTargetPool.FindFreeElement(Desc, Target, Name); SetRenderTarget(RHICmdList, Target->GetRenderTargetItem().TargetableTexture, FTextureRHIRef()); RHICmdList.Clear(true, FLinearColor(0, 0, 0, 0), false, 1.0f, false, 0, FIntRect()); } }
void SetParameters(FRHICommandList& RHICmdList, const ShaderRHIParamRef& ShaderRHI, const TRefCountPtr<IPooledRenderTarget>& DynamicBentNormalAO, float SkySpecularOcclusionStrength, float MinOcclusionValue) { FTextureRHIParamRef BentNormalAO = GWhiteTexture->TextureRHI; bool bApplyBentNormalAO = false; if (DynamicBentNormalAO) { BentNormalAO = DynamicBentNormalAO->GetRenderTargetItem().ShaderResourceTexture; bApplyBentNormalAO = true; } SetTextureParameter(RHICmdList, ShaderRHI, BentNormalAOTexture, BentNormalAOSampler, TStaticSamplerState<SF_Point>::GetRHI(), BentNormalAO); SetShaderValue(RHICmdList, ShaderRHI, ApplyBentNormalAO, bApplyBentNormalAO ? 1.0f : 0.0f); SetShaderValue(RHICmdList, ShaderRHI, InvSkySpecularOcclusionStrength, 1.0f / FMath::Max(SkySpecularOcclusionStrength, .1f)); SetShaderValue(RHICmdList, ShaderRHI, MinSkySpecularOcclusion, MinOcclusionValue); }
void DownsamplePass(FRHICommandListImmediate& RHICmdList, const FViewInfo& View, const FLightSceneInfo* LightSceneInfo, TRefCountPtr<IPooledRenderTarget>& LightShaftsSource, TRefCountPtr<IPooledRenderTarget>& LightShaftsDest) { const FIntPoint BufferSize = FSceneRenderTargets::Get(RHICmdList).GetBufferSizeXY(); const uint32 DownsampleFactor = GetLightShaftDownsampleFactor(); const FIntPoint FilterBufferSize = BufferSize / DownsampleFactor; const FIntPoint DownSampledXY = View.ViewRect.Min / DownsampleFactor; const uint32 DownsampledSizeX = View.ViewRect.Width() / DownsampleFactor; const uint32 DownsampledSizeY = View.ViewRect.Height() / DownsampleFactor; SetRenderTarget(RHICmdList, LightShaftsDest->GetRenderTargetItem().TargetableTexture, FTextureRHIRef()); RHICmdList.SetViewport(DownSampledXY.X, DownSampledXY.Y, 0.0f, DownSampledXY.X + DownsampledSizeX, DownSampledXY.Y + DownsampledSizeY, 1.0f); // Set shaders and texture TShaderMapRef<FDownsampleLightShaftsVertexShader> DownsampleLightShaftsVertexShader(View.ShaderMap); TRefCountPtr<IPooledRenderTarget> UnusedRT; switch(LightSceneInfo->Proxy->GetLightType()) { case LightType_Directional: { TShaderMapRef<TDownsampleLightShaftsPixelShader<LightType_Directional, bDownsampleOcclusion> > DownsampleLightShaftsPixelShader(View.ShaderMap); SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), DownsampleDirectionalLightShaftsBoundShaderState[bDownsampleOcclusion], GFilterVertexDeclaration.VertexDeclarationRHI, *DownsampleLightShaftsVertexShader, *DownsampleLightShaftsPixelShader); DownsampleLightShaftsPixelShader->SetParameters(RHICmdList, LightSceneInfo, View, UnusedRT); } break; case LightType_Spot: { TShaderMapRef<TDownsampleLightShaftsPixelShader<LightType_Spot, bDownsampleOcclusion> > DownsampleLightShaftsPixelShader(View.ShaderMap); SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), DownsampleSpotLightShaftsBoundShaderState[bDownsampleOcclusion], GFilterVertexDeclaration.VertexDeclarationRHI, *DownsampleLightShaftsVertexShader, *DownsampleLightShaftsPixelShader); DownsampleLightShaftsPixelShader->SetParameters(RHICmdList, LightSceneInfo, View, UnusedRT); } break; default: case LightType_Point: { TShaderMapRef<TDownsampleLightShaftsPixelShader<LightType_Point, bDownsampleOcclusion> > DownsampleLightShaftsPixelShader(View.ShaderMap); SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), DownsamplePointLightShaftsBoundShaderState[bDownsampleOcclusion], GFilterVertexDeclaration.VertexDeclarationRHI, *DownsampleLightShaftsVertexShader, *DownsampleLightShaftsPixelShader); DownsampleLightShaftsPixelShader->SetParameters(RHICmdList, LightSceneInfo, View, UnusedRT); } break; } DownsampleLightShaftsVertexShader->SetParameters(RHICmdList, View); // No depth tests, no backface culling. RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<FM_Solid, CM_None>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI()); // Downsample scene color and depth, and convert them into a bloom term and an occlusion masking term DrawRectangle( RHICmdList, 0, 0, DownsampledSizeX, DownsampledSizeY, View.ViewRect.Min.X, View.ViewRect.Min.Y, View.ViewRect.Width(), View.ViewRect.Height(), FIntPoint(DownsampledSizeX, DownsampledSizeY), BufferSize, *DownsampleLightShaftsVertexShader, EDRF_UseTriangleOptimization); RHICmdList.CopyToResolveTarget(LightShaftsDest->GetRenderTargetItem().TargetableTexture, LightShaftsDest->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams()); Swap(LightShaftsSource, LightShaftsDest); }
void SetParameters(FRHICommandList& RHICmdList, const ShaderRHIParamRef Shader, const FLightSceneInfo* LightSceneInfo, const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& PassSource) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const uint32 DownsampleFactor = GetLightShaftDownsampleFactor(); FIntPoint DownSampledViewSize(FMath::FloorToInt(View.ViewRect.Width() / DownsampleFactor), FMath::FloorToInt(View.ViewRect.Height() / DownsampleFactor)); const FIntPoint FilterBufferSize = SceneContext.GetBufferSizeXY() / DownsampleFactor; const FVector2D ViewRatioOfBuffer((float)DownSampledViewSize.X / FilterBufferSize.X, (float)DownSampledViewSize.Y / FilterBufferSize.Y); const FVector4 AspectRatioAndInvAspectRatio( ViewRatioOfBuffer.X, (float)FilterBufferSize.X * ViewRatioOfBuffer.Y / FilterBufferSize.Y, 1.0f / ViewRatioOfBuffer.X, (float)FilterBufferSize.Y / (FilterBufferSize.X * ViewRatioOfBuffer.Y)); SetShaderValue(RHICmdList, Shader, AspectRatioAndInvAspectRatioParameter, AspectRatioAndInvAspectRatio); const FVector WorldSpaceBlurOrigin = LightSceneInfo->Proxy->GetLightPositionForLightShafts(View.ViewMatrices.ViewOrigin); // Transform into texture coordinates FVector4 ProjectedBlurOrigin = View.WorldToScreen(WorldSpaceBlurOrigin); const FIntPoint BufferSize = SceneContext.GetBufferSizeXY(); const float InvBufferSizeX = 1.0f / BufferSize.X; const float InvBufferSizeY = 1.0f / BufferSize.Y; FVector2D ScreenSpaceBlurOrigin; { verify(ProjectedBlurOrigin.W > 0.0f); float InvW = 1.0f / ProjectedBlurOrigin.W; float Y = (GProjectionSignY > 0.0f) ? ProjectedBlurOrigin.Y : 1.0f - ProjectedBlurOrigin.Y; ScreenSpaceBlurOrigin = FVector2D( View.ViewRect.Min.X + (0.5f + ProjectedBlurOrigin.X * 0.5f * InvW) * View.ViewRect.Width(), View.ViewRect.Min.Y + (0.5f - Y * 0.5f * InvW) * View.ViewRect.Height() ); } ScreenSpaceBlurOrigin.X *= InvBufferSizeX; ScreenSpaceBlurOrigin.Y *= InvBufferSizeY; FVector2D TextureSpaceBlurOrigin(ScreenSpaceBlurOrigin * FVector2D(AspectRatioAndInvAspectRatio.Z, AspectRatioAndInvAspectRatio.W)); SetShaderValue(RHICmdList, Shader, TextureSpaceBlurOriginParameter, TextureSpaceBlurOrigin); SetShaderValue(RHICmdList, Shader, WorldSpaceBlurOriginAndRadiusParameter, FVector4(WorldSpaceBlurOrigin, LightSceneInfo->Proxy->GetRadius())); SetShaderValue(RHICmdList, Shader, LightSourceRadius, LightSceneInfo->Proxy->GetSourceRadius()); const bool bIsSpotLight = LightSceneInfo->Proxy->GetLightType() == LightType_Spot; if (bIsSpotLight) { SetShaderValue(RHICmdList, Shader, WorldSpaceSpotDirectionParameter, LightSceneInfo->Proxy->GetDirection()); SetShaderValue(RHICmdList, Shader, SpotAnglesParameter, LightSceneInfo->Proxy->GetLightShaftConeParams()); } const float DistanceFromLight = (View.ViewMatrices.ViewOrigin - WorldSpaceBlurOrigin).Size() + PointLightFadeDistanceIncrease; SetShaderValue(RHICmdList, Shader, WorldSpaceCameraPositionParameter, FVector4(View.ViewMatrices.ViewOrigin, DistanceFromLight)); const FIntPoint DownSampledXY = View.ViewRect.Min / DownsampleFactor; const uint32 DownsampledSizeX = View.ViewRect.Width() / DownsampleFactor; const uint32 DownsampledSizeY = View.ViewRect.Height() / DownsampleFactor; // Limits for where the pixel shader is allowed to sample // Prevents reading from outside the valid region of a render target // Clamp to 1 less than the actual max, // Since the bottom-right row/column of texels will contain some unwanted values if the size of scene color is not a factor of the downsample factor float MinU, MinV, MaxU, MaxV; { MinU = DownSampledXY.X / (float)FilterBufferSize.X; MinV = DownSampledXY.Y / (float)FilterBufferSize.Y; MaxU = (float(DownSampledXY.X) + DownsampledSizeX - 1) / (float)FilterBufferSize.X; MaxV = (float(DownSampledXY.Y) + DownsampledSizeY - 1) / (float)FilterBufferSize.Y; } FVector4 UVMinMax( MinU, MinV, MaxU, MaxV ); SetShaderValue(RHICmdList, Shader, UVMinMaxParameter, UVMinMax); const FLinearColor BloomTint = LightSceneInfo->BloomTint; SetShaderValue(RHICmdList, Shader, BloomTintAndThresholdParameter, FVector4(BloomTint.R, BloomTint.G, BloomTint.B, LightSceneInfo->BloomThreshold)); float OcclusionMaskDarkness; float OcclusionDepthRange; LightSceneInfo->Proxy->GetLightShaftOcclusionParameters(OcclusionMaskDarkness, OcclusionDepthRange); const FVector4 LightShaftParameterValues(1.0f / OcclusionDepthRange, LightSceneInfo->BloomScale, 1, OcclusionMaskDarkness); SetShaderValue(RHICmdList, Shader, LightShaftParameters, LightShaftParameterValues); float DistanceFade = 0.0f; if (LightSceneInfo->Proxy->GetLightType() != LightType_Directional) { DistanceFade = FMath::Clamp(DistanceFromLight / (LightSceneInfo->Proxy->GetRadius() * PointLightRadiusFadeFactor), 0.0f, 1.0f); } SetShaderValue(RHICmdList, Shader, DistanceFadeParameter, DistanceFade); if (IsValidRef(PassSource)) { SetTextureParameter( RHICmdList, Shader, SourceTextureParameter, SourceTextureSamplerParameter, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), PassSource->GetRenderTargetItem().ShaderResourceTexture ); } }
void FRCPassPostProcessWeightedSampleSum::Process(FRenderingCompositePassContext& Context) { const FSceneView& View = Context.View; FRenderingCompositeOutput *Input = PassInputs[0].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; // e.g. 4 means the input texture is 4x smaller than the buffer size FIntPoint SrcScaleFactor = GSceneRenderTargets.GetBufferSizeXY() / SrcSize; FIntPoint DstScaleFactor = GSceneRenderTargets.GetBufferSizeXY() / DestSize; TRefCountPtr<IPooledRenderTarget> InputPooledElement = Input->RequestInput(); check(!InputPooledElement->IsFree()); const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); 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; // 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); SCOPED_DRAW_EVENTF(Context.RHICmdList, PostProcessWeightedSampleSum, TEXT("PostProcessWeightedSampleSum#%d"), NumSamples); // 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()); 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()); const FTextureRHIRef& FilterTexture = InputPooledElement->GetRenderTargetItem().ShaderResourceTexture; FRenderingCompositeOutput *Input1 = PassInputs[1].GetOutput(); 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; } bool bDoFastBlur = DoFastBlur(); 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 ); 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); FIntRect DestRect = FIntRect::DivideAndRoundUp(View.ViewRect, DstScaleFactor); DrawQuad(Context.RHICmdList, bDoFastBlur, SrcRect, DestRect, bRequiresClear, DestSize, SrcSize, VertexShader); Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); }
void SetParameters(const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& Src) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(ShaderRHI, View); SetTextureParameter(ShaderRHI, InputTexture, InputTextureSampler, TStaticSamplerState<>::GetRHI(), Src->GetRenderTargetItem().ShaderResourceTexture); }
void FRCPassPostProcessVisualizeLPV::Process(FRenderingCompositePassContext& Context) { SCOPED_DRAW_EVENT(Context.RHICmdList, VisualizeLPV); const FSceneView& View = Context.View; const FSceneViewFamily& ViewFamily = *(View.Family); // const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context); const TRefCountPtr<IPooledRenderTarget> RenderTarget = GetInput(ePId_Input0)->GetOutput()->PooledRenderTarget; const FSceneRenderTargetItem& DestRenderTarget = RenderTarget->GetRenderTargetItem(); // Set the view family's render target/viewport. SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef()); { // 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, View.GetFeatureLevel()); float X = 30; float Y = 28; const float YStep = 14; const float ColumnWidth = 250; Canvas.DrawShadowedString( X, Y += YStep, TEXT("VisualizeLightPropagationVolume"), GetStatsFont(), FLinearColor(0.2f, 0.2f, 1)); Y += YStep; const FLightPropagationVolumeSettings& Dest = View.FinalPostProcessSettings.BlendableManager.GetSingleFinalDataConst<FLightPropagationVolumeSettings>(); #define ENTRY(name)\ Canvas.DrawShadowedString( X, Y += YStep, TEXT(#name) TEXT(":"), GetStatsFont(), FLinearColor(1, 1, 1));\ Canvas.DrawShadowedString( X + ColumnWidth, Y, *FString::Printf(TEXT("%g"), Dest.name), GetStatsFont(), FLinearColor(1, 1, 1)); ENTRY(LPVIntensity) ENTRY(LPVVplInjectionBias) ENTRY(LPVSize) ENTRY(LPVSecondaryOcclusionIntensity) ENTRY(LPVSecondaryBounceIntensity) ENTRY(LPVGeometryVolumeBias) ENTRY(LPVEmissiveInjectionIntensity) ENTRY(LPVDirectionalOcclusionIntensity) ENTRY(LPVDirectionalOcclusionRadius) ENTRY(LPVDiffuseOcclusionExponent) ENTRY(LPVSpecularOcclusionExponent) ENTRY(LPVDiffuseOcclusionIntensity) ENTRY(LPVSpecularOcclusionIntensity) #undef ENTRY Canvas.Flush_RenderThread(Context.RHICmdList); } Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams()); // to satify following passws FRenderingCompositeOutput* Output = GetOutput(ePId_Output0); Output->PooledRenderTarget = RenderTarget; }
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 FHZBOcclusionTester::Submit(FRHICommandListImmediate& RHICmdList, const FViewInfo& View) { SCOPED_DRAW_EVENT(RHICmdList, SubmitHZB); FSceneViewState* ViewState = (FSceneViewState*)View.State; if( !ViewState ) { return; } TRefCountPtr< IPooledRenderTarget > BoundsCenterTexture; TRefCountPtr< IPooledRenderTarget > BoundsExtentTexture; { uint32 Flags = TexCreate_ShaderResource | TexCreate_Dynamic; FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( FIntPoint( SizeX, SizeY ), PF_A32B32G32R32F, FClearValueBinding::None, Flags, TexCreate_None, false ) ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, BoundsCenterTexture, TEXT("HZBBoundsCenter") ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, BoundsExtentTexture, TEXT("HZBBoundsExtent") ); } TRefCountPtr< IPooledRenderTarget > ResultsTextureGPU; { FPooledRenderTargetDesc Desc( FPooledRenderTargetDesc::Create2DDesc( FIntPoint( SizeX, SizeY ), PF_B8G8R8A8, FClearValueBinding::None, TexCreate_None, TexCreate_RenderTargetable, false ) ); GRenderTargetPool.FindFreeElement(RHICmdList, Desc, ResultsTextureGPU, TEXT("HZBResultsGPU") ); } { #if 0 static float CenterBuffer[ SizeX * SizeY ][4]; static float ExtentBuffer[ SizeX * SizeY ][4]; FMemory::Memset( CenterBuffer, 0, sizeof( CenterBuffer ) ); FMemory::Memset( ExtentBuffer, 0, sizeof( ExtentBuffer ) ); const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i++ ) { const FOcclusionPrimitive& Primitive = Primitives[i]; CenterBuffer[i][0] = Primitive.Center.X; CenterBuffer[i][1] = Primitive.Center.Y; CenterBuffer[i][2] = Primitive.Center.Z; CenterBuffer[i][3] = 0.0f; ExtentBuffer[i][0] = Primitive.Extent.X; ExtentBuffer[i][1] = Primitive.Extent.Y; ExtentBuffer[i][2] = Primitive.Extent.Z; ExtentBuffer[i][3] = 1.0f; } FUpdateTextureRegion2D Region( 0, 0, 0, 0, SizeX, SizeY ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)ExtentBuffer ); #elif 0 static float CenterBuffer[ SizeX * SizeY ][4]; static float ExtentBuffer[ SizeX * SizeY ][4]; { QUICK_SCOPE_CYCLE_COUNTER(STAT_HZBPackPrimitiveData); FMemory::Memset( CenterBuffer, 0, sizeof( CenterBuffer ) ); FMemory::Memset( ExtentBuffer, 0, sizeof( ExtentBuffer ) ); const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i++ ) { const FOcclusionPrimitive& Primitive = Primitives[i]; uint32 x = FMath::ReverseMortonCode2( i >> 0 ); uint32 y = FMath::ReverseMortonCode2( i >> 1 ); uint32 m = x + y * SizeX; CenterBuffer[m][0] = Primitive.Center.X; CenterBuffer[m][1] = Primitive.Center.Y; CenterBuffer[m][2] = Primitive.Center.Z; CenterBuffer[m][3] = 0.0f; ExtentBuffer[m][0] = Primitive.Extent.X; ExtentBuffer[m][1] = Primitive.Extent.Y; ExtentBuffer[m][2] = Primitive.Extent.Z; ExtentBuffer[m][3] = 1.0f; } } QUICK_SCOPE_CYCLE_COUNTER(STAT_HZBUpdateTextures); FUpdateTextureRegion2D Region( 0, 0, 0, 0, SizeX, SizeY ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, SizeX * 4 * sizeof( float ), (uint8*)ExtentBuffer ); #else // Update in blocks to avoid large update const uint32 BlockSize = 8; const uint32 SizeInBlocksX = SizeX / BlockSize; const uint32 SizeInBlocksY = SizeY / BlockSize; const uint32 BlockStride = BlockSize * 4 * sizeof( float ); float CenterBuffer[ BlockSize * BlockSize ][4]; float ExtentBuffer[ BlockSize * BlockSize ][4]; const uint32 NumPrimitives = Primitives.Num(); for( uint32 i = 0; i < NumPrimitives; i += BlockSize * BlockSize ) { const uint32 BlockEnd = FMath::Min( BlockSize * BlockSize, NumPrimitives - i ); for( uint32 b = 0; b < BlockEnd; b++ ) { const FOcclusionPrimitive& Primitive = Primitives[ i + b ]; CenterBuffer[b][0] = Primitive.Center.X; CenterBuffer[b][1] = Primitive.Center.Y; CenterBuffer[b][2] = Primitive.Center.Z; CenterBuffer[b][3] = 0.0f; ExtentBuffer[b][0] = Primitive.Extent.X; ExtentBuffer[b][1] = Primitive.Extent.Y; ExtentBuffer[b][2] = Primitive.Extent.Z; ExtentBuffer[b][3] = 1.0f; } // Clear rest of block if( BlockEnd < BlockSize * BlockSize ) { FMemory::Memset( (float*)CenterBuffer + BlockEnd * 4, 0, sizeof( CenterBuffer ) - BlockEnd * 4 * sizeof(float) ); FMemory::Memset( (float*)ExtentBuffer + BlockEnd * 4, 0, sizeof( ExtentBuffer ) - BlockEnd * 4 * sizeof(float) ); } const int32 BlockIndex = i / (BlockSize * BlockSize); const int32 BlockX = BlockIndex % SizeInBlocksX; const int32 BlockY = BlockIndex / SizeInBlocksY; FUpdateTextureRegion2D Region( BlockX * BlockSize, BlockY * BlockSize, 0, 0, BlockSize, BlockSize ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, BlockStride, (uint8*)CenterBuffer ); RHIUpdateTexture2D( (FTexture2DRHIRef&)BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture, 0, Region, BlockStride, (uint8*)ExtentBuffer ); } #endif Primitives.Empty(); } // Draw test { SCOPED_DRAW_EVENT(RHICmdList, TestHZB); SetRenderTarget(RHICmdList, ResultsTextureGPU->GetRenderTargetItem().TargetableTexture, NULL); RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI()); RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI()); RHICmdList.SetDepthStencilState(TStaticDepthStencilState< false, CF_Always >::GetRHI()); TShaderMapRef< FScreenVS > VertexShader(View.ShaderMap); TShaderMapRef< FHZBTestPS > PixelShader(View.ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, BoundsCenterTexture->GetRenderTargetItem().ShaderResourceTexture, BoundsExtentTexture->GetRenderTargetItem().ShaderResourceTexture ); RHICmdList.SetViewport(0, 0, 0.0f, SizeX, SizeY, 1.0f); // TODO draw quads covering blocks added above DrawRectangle( RHICmdList, 0, 0, SizeX, SizeY, 0, 0, SizeX, SizeY, FIntPoint( SizeX, SizeY ), FIntPoint( SizeX, SizeY ), *VertexShader, EDRF_UseTriangleOptimization); } GRenderTargetPool.VisualizeTexture.SetCheckPoint(RHICmdList, ResultsTextureGPU); // Transfer memory GPU -> CPU RHICmdList.CopyToResolveTarget(ResultsTextureGPU->GetRenderTargetItem().TargetableTexture, ResultsTextureCPU->GetRenderTargetItem().ShaderResourceTexture, false, FResolveParams()); }
void SetPS(const FRenderingCompositePassContext& Context) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View); DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View); const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings; const FSceneViewFamily& ViewFamily = *(Context.View.Family); FSceneViewState* ViewState = (FSceneViewState*)Context.View.State; PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI()); // PostprocessInput1MS and EditorPrimitivesStencil { FRenderingCompositeOutputRef* OutputRef = Context.Pass->GetInput(ePId_Input1); check(OutputRef); FRenderingCompositeOutput* Input = OutputRef->GetOutput(); check(Input); TRefCountPtr<IPooledRenderTarget> InputPooledElement = Input->RequestInput(); check(InputPooledElement); FTexture2DRHIRef& TargetableTexture = (FTexture2DRHIRef&)InputPooledElement->GetRenderTargetItem().TargetableTexture; SetTextureParameter(Context.RHICmdList, ShaderRHI, PostprocessInput1MS, TargetableTexture); if(EditorPrimitivesStencil.IsBound()) { // cache the stencil SRV to avoid create calls each frame (the cache element is stored in the state) if(ViewState->SelectionOutlineCacheKey != TargetableTexture) { // release if not the right one (as the internally SRV stores a pointer to the texture we cannot get a false positive) ViewState->SelectionOutlineCacheKey.SafeRelease(); ViewState->SelectionOutlineCacheValue.SafeRelease(); } if(!ViewState->SelectionOutlineCacheValue) { // create if needed ViewState->SelectionOutlineCacheKey = TargetableTexture; ViewState->SelectionOutlineCacheValue = RHICreateShaderResourceView(TargetableTexture, 0, 1, PF_X24_G8); } SetSRVParameter(Context.RHICmdList, ShaderRHI, EditorPrimitivesStencil, ViewState->SelectionOutlineCacheValue); } } #if WITH_EDITOR { FLinearColor OutlineColorValue = Context.View.SelectionOutlineColor; FLinearColor SubduedOutlineColorValue = Context.View.SubduedSelectionOutlineColor; OutlineColorValue.A = GEngine->SelectionHighlightIntensity; SetShaderValue(Context.RHICmdList, ShaderRHI, OutlineColor, OutlineColorValue); SetShaderValue(Context.RHICmdList, ShaderRHI, SubduedOutlineColor, SubduedOutlineColorValue); SetShaderValue(Context.RHICmdList, ShaderRHI, BSPSelectionIntensity, GEngine->BSPSelectionHighlightIntensity); } #else check(!"This shader is not used outside of the Editor."); #endif { static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.Editor.MovingPattern")); FLinearColor Value(0, CVar->GetValueOnRenderThread(), 0, 0); if(!ViewFamily.bRealtimeUpdate) { // no animation if realtime update is disabled Value.G = 0; } SetShaderValue(Context.RHICmdList, ShaderRHI, EditorRenderParams, Value); } }