- // Post Process Material Chain - Before Translucency
- {
- const FPostProcessMaterialChain MaterialChain = GetPostProcessMaterialChain(View, BL_BeforeTranslucency);
-
- if (MaterialChain.Num())
- {
- SceneColor = AddPostProcessMaterialChain(GraphBuilder, View, GetPostProcessMaterialInputs(SceneColor), MaterialChain);
- }
- }
-
- FScreenPassTexture AddPostProcessMaterialChain(
- FRDGBuilder& GraphBuilder,
- const FViewInfo& View,
- const FPostProcessMaterialInputs& InputsTemplate,
- const FPostProcessMaterialChain& Materials)
- {
- FScreenPassTexture Outputs = InputsTemplate.GetInput(EPostProcessMaterialInput::SceneColor);
-
- bool bFirstMaterialInChain = true;
- for (const UMaterialInterface* MaterialInterface : Materials)
- {
- FPostProcessMaterialInputs Inputs = InputsTemplate;
- Inputs.SetInput(EPostProcessMaterialInput::SceneColor, Outputs);
-
- // Only the first material in the chain needs to decode the input color
- Inputs.bMetalMSAAHDRDecode = Inputs.bMetalMSAAHDRDecode && bFirstMaterialInChain;
- bFirstMaterialInChain = false;
-
- // Certain inputs are only respected by the final post process material in the chain.
- if (MaterialInterface != Materials.Last())
- {
- Inputs.OverrideOutput = FScreenPassRenderTarget();
- Inputs.bFlipYAxis = false;
- }
-
- Outputs = AddPostProcessMaterialPass(GraphBuilder, View, Inputs, MaterialInterface);
- }
-
- return Outputs;
- }
- FScreenPassTexture AddPostProcessMaterialPass(
- FRDGBuilder& GraphBuilder,
- const FViewInfo& View,
- const FPostProcessMaterialInputs& Inputs,
- const UMaterialInterface* MaterialInterface)
- {
- Inputs.Validate();
-
- const FScreenPassTexture SceneColor = Inputs.GetInput(EPostProcessMaterialInput::SceneColor);
-
- const ERHIFeatureLevel::Type FeatureLevel = View.GetFeatureLevel();
-
- const FMaterial* Material = nullptr;
- const FMaterialRenderProxy* MaterialRenderProxy = nullptr;
- const FMaterialShaderMap* MaterialShaderMap = nullptr;
- GetMaterialInfo(MaterialInterface, FeatureLevel, Inputs.OutputFormat, Material, MaterialRenderProxy, MaterialShaderMap);
-
- FRHIDepthStencilState* DefaultDepthStencilState = FScreenPassPipelineState::FDefaultDepthStencilState::GetRHI();
- FRHIDepthStencilState* DepthStencilState = DefaultDepthStencilState;
-
- FRDGTextureRef DepthStencilTexture = nullptr;
-
- // Allocate custom depth stencil texture(s) and depth stencil state.
- const ECustomDepthPolicy CustomStencilPolicy = GetMaterialCustomDepthPolicy(Material, FeatureLevel);
-
- if (CustomStencilPolicy == ECustomDepthPolicy::Enabled)
- {
- check(Inputs.CustomDepthTexture);
- DepthStencilTexture = Inputs.CustomDepthTexture;
- DepthStencilState = GetMaterialStencilState(Material);
- }
-
- FRHIBlendState* DefaultBlendState = FScreenPassPipelineState::FDefaultBlendState::GetRHI();
- FRHIBlendState* BlendState = DefaultBlendState;
-
- if (IsMaterialBlendEnabled(Material))
- {
- BlendState = GetMaterialBlendState(Material);
- }
-
- // Blend / Depth Stencil usage requires that the render target have primed color data.
- const bool bCompositeWithInput = DepthStencilState != DefaultDepthStencilState || BlendState != DefaultBlendState;
-
- // We only prime color on the output texture if we are using fixed function Blend / Depth-Stencil,
- // or we need to retain previously rendered views.
- const bool bPrimeOutputColor = bCompositeWithInput || !View.IsFirstInFamily();
-
- // Inputs.OverrideOutput is used to force drawing directly to the backbuffer. OpenGL doesn't support using the backbuffer color target with a custom depth/stencil
- // buffer, so in that case we must draw to an intermediate target and copy to the backbuffer at the end. Ideally, we would test if Inputs.OverrideOutput.Texture
- // is actually the backbuffer (as returned by AndroidEGL::GetOnScreenColorRenderBuffer() and such), but it's not worth doing all the plumbing and increasing the
- // RHI surface area just for this hack.
- const bool bBackbufferWithDepthStencil = (DepthStencilTexture != nullptr && !GRHISupportsBackBufferWithCustomDepthStencil && Inputs.OverrideOutput.IsValid());
-
- // The other case when we must render to an intermediate target is when we have to flip the image vertically because we're the last postprocess pass on mobile OpenGL.
- // We can't simply output a flipped image, because the parts of the input image which show through the stencil mask or are blended in must also be flipped. In that case,
- // we render normally to the intermediate target and flip the image when we copy to the output target.
- const bool bCompositeWithInputAndFlipY = bCompositeWithInput && Inputs.bFlipYAxis;
-
- // We need to decode the target color for blending material, force it rendering to an intermediate render target and decode the color.
- const bool bCompositeWithInputAndDecode = Inputs.bMetalMSAAHDRDecode && bCompositeWithInput;
-
- const bool bForceIntermediateTarget = bBackbufferWithDepthStencil || bCompositeWithInputAndFlipY || bCompositeWithInputAndDecode;
-
- FScreenPassRenderTarget Output = Inputs.OverrideOutput;
-
- // We can re-use the scene color texture as the render target if we're not simultaneously reading from it.
- // This is only necessary to do if we're going to be priming content from the render target since it avoids
- // the copy. Otherwise, we just allocate a new render target.
- if (!Output.IsValid() && !MaterialShaderMap->UsesSceneTexture(PPI_PostProcessInput0) && bPrimeOutputColor && !bForceIntermediateTarget && Inputs.bAllowSceneColorInputAsOutput)
- {
- Output = FScreenPassRenderTarget(SceneColor, ERenderTargetLoadAction::ELoad);
- }
- else
- {
- // Allocate new transient output texture if none exists.
- if (!Output.IsValid() || bForceIntermediateTarget)
- {
- FRDGTextureDesc OutputDesc = SceneColor.Texture->Desc;
- OutputDesc.Reset();
- if (Inputs.OutputFormat != PF_Unknown)
- {
- OutputDesc.Format = Inputs.OutputFormat;
- }
- OutputDesc.ClearValue = FClearValueBinding(FLinearColor::Black);
- OutputDesc.Flags |= GFastVRamConfig.PostProcessMaterial;
-
- Output = FScreenPassRenderTarget(GraphBuilder.CreateTexture(OutputDesc, TEXT("PostProcessMaterial")), SceneColor.ViewRect, View.GetOverwriteLoadAction());
- }
-
- if (bPrimeOutputColor || bForceIntermediateTarget)
- {
- // Copy existing contents to new output and use load-action to preserve untouched pixels.
- if (Inputs.bMetalMSAAHDRDecode)
- {
- AddMobileMSAADecodeAndDrawTexturePass(GraphBuilder, View, SceneColor, Output);
- }
- else
- {
- AddDrawTexturePass(GraphBuilder, View, SceneColor, Output);
- }
- Output.LoadAction = ERenderTargetLoadAction::ELoad;
- }
- }
-
- const FScreenPassTextureViewport SceneColorViewport(SceneColor);
- const FScreenPassTextureViewport OutputViewport(Output);
-
- RDG_EVENT_SCOPE(GraphBuilder, "PostProcessMaterial %dx%d Material=%s", SceneColorViewport.Rect.Width(), SceneColorViewport.Rect.Height(), *Material->GetFriendlyName());
-
- const uint32 MaterialStencilRef = Material->GetStencilRefValue();
-
- const bool bMobilePlatform = IsMobilePlatform(View.GetShaderPlatform());
-
- FPostProcessMaterialParameters* PostProcessMaterialParameters = GraphBuilder.AllocParameters
(); - PostProcessMaterialParameters->SceneTextures = Inputs.SceneTextures;
- PostProcessMaterialParameters->View = View.ViewUniformBuffer;
- if (bMobilePlatform)
- {
- PostProcessMaterialParameters->EyeAdaptationBuffer = GetEyeAdaptationBuffer(View);
- }
- else
- {
- PostProcessMaterialParameters->EyeAdaptationTexture = GetEyeAdaptationTexture(GraphBuilder, View);
- }
- PostProcessMaterialParameters->PostProcessOutput = GetScreenPassTextureViewportParameters(OutputViewport);
- PostProcessMaterialParameters->MobileCustomStencilTexture = DepthStencilTexture;
- PostProcessMaterialParameters->MobileCustomStencilTextureSampler = TStaticSamplerState
::GetRHI(); - PostProcessMaterialParameters->MobileStencilValueRef = MaterialStencilRef;
- PostProcessMaterialParameters->RenderTargets[0] = Output.GetRenderTargetBinding();
-
- // The target color will be decoded if bForceIntermediateTarget is true in any case, but we might still need to decode the input color
- PostProcessMaterialParameters->bMetalMSAAHDRDecode = Inputs.bMetalMSAAHDRDecode ? 1 : 0;
-
- if (DepthStencilTexture && !bMobilePlatform)
- {
- PostProcessMaterialParameters->RenderTargets.DepthStencil = FDepthStencilBinding(
- DepthStencilTexture,
- ERenderTargetLoadAction::ELoad,
- ERenderTargetLoadAction::ELoad,
- FExclusiveDepthStencil::DepthRead_StencilRead);
- }
- else if (!DepthStencilTexture && bMobilePlatform && Material->IsStencilTestEnabled()) // we have to set a default texture for MobileStencilTexture and override the MobileStencilValueRef to make all function to pass the stencil test
- {
- PostProcessMaterialParameters->MobileCustomStencilTexture = GSystemTextures.GetBlackDummy(GraphBuilder);
-
- switch (Material->GetStencilCompare())
- {
- case EMaterialStencilCompare::MSC_Less:
- PostProcessMaterialParameters->MobileStencilValueRef = -1;
- break;
- case EMaterialStencilCompare::MSC_LessEqual:
- case EMaterialStencilCompare::MSC_GreaterEqual:
- case EMaterialStencilCompare::MSC_Equal:
- PostProcessMaterialParameters->MobileStencilValueRef = 0;
- break;
- case EMaterialStencilCompare::MSC_Greater:
- case EMaterialStencilCompare::MSC_NotEqual:
- PostProcessMaterialParameters->MobileStencilValueRef = 1;
- break;
- case EMaterialStencilCompare::MSC_Always:
- PostProcessMaterialParameters->MobileStencilValueRef = 256;
- break;
- default:
- break;
- }
- }
-
- PostProcessMaterialParameters->PostProcessInput_BilinearSampler = TStaticSamplerState
::GetRHI();; -
- const FScreenPassTexture BlackDummy(GSystemTextures.GetBlackDummy(GraphBuilder));
-
- // This gets passed in whether or not it's used.
- GraphBuilder.RemoveUnusedTextureWarning(BlackDummy.Texture);
-
- FRHISamplerState* PointClampSampler = TStaticSamplerState
::GetRHI(); -
- for (uint32 InputIndex = 0; InputIndex < kPostProcessMaterialInputCountMax; ++InputIndex)
- {
- FScreenPassTexture Input = Inputs.GetInput((EPostProcessMaterialInput)InputIndex);
-
- // Need to provide valid textures for when shader compilation doesn't cull unused parameters.
- if (!Input.Texture || !MaterialShaderMap->UsesSceneTexture(PPI_PostProcessInput0 + InputIndex))
- {
- Input = BlackDummy;
- }
-
- PostProcessMaterialParameters->PostProcessInput[InputIndex] = GetScreenPassTextureInput(Input, PointClampSampler);
- }
-
- const bool bIsMobile = FeatureLevel <= ERHIFeatureLevel::ES3_1;
-
- PostProcessMaterialParameters->bFlipYAxis = Inputs.bFlipYAxis && !bForceIntermediateTarget;
-
- FPostProcessMaterialShader::FPermutationDomain PermutationVector;
- PermutationVector.Set
(bIsMobile); -
- TShaderRef
VertexShader = MaterialShaderMap->GetShader(PermutationVector); - TShaderRef
PixelShader = MaterialShaderMap->GetShader(PermutationVector); - ClearUnusedGraphResources(VertexShader, PixelShader, PostProcessMaterialParameters);
-
- EScreenPassDrawFlags ScreenPassFlags = EScreenPassDrawFlags::AllowHMDHiddenAreaMask;
-
- if (PostProcessMaterialParameters->bFlipYAxis)
- {
- ScreenPassFlags |= EScreenPassDrawFlags::FlipYAxis;
- }
-
- AddDrawScreenPass(
- GraphBuilder,
- RDG_EVENT_NAME("PostProcessMaterial"),
- View,
- OutputViewport,
- SceneColorViewport,
- FScreenPassPipelineState(VertexShader, PixelShader, BlendState, DepthStencilState),
- PostProcessMaterialParameters,
- ScreenPassFlags,
- [&View, VertexShader, PixelShader, MaterialRenderProxy, PostProcessMaterialParameters, MaterialStencilRef](FRHICommandListImmediate& RHICmdList)
- {
- FPostProcessMaterialVS::SetParameters(RHICmdList, VertexShader, View, MaterialRenderProxy, *PostProcessMaterialParameters);
- FPostProcessMaterialPS::SetParameters(RHICmdList, PixelShader, View, MaterialRenderProxy, *PostProcessMaterialParameters);
- RHICmdList.SetStencilRef(MaterialStencilRef);
- });
-
- if (bForceIntermediateTarget && !bCompositeWithInputAndDecode)
- {
- if (!Inputs.bFlipYAxis)
- {
- // We shouldn't get here unless we had an override target.
- check(Inputs.OverrideOutput.IsValid());
- AddDrawTexturePass(GraphBuilder, View, Output.Texture, Inputs.OverrideOutput.Texture);
- Output = Inputs.OverrideOutput;
- }
- else
- {
- FScreenPassRenderTarget TempTarget = Output;
- if (Inputs.OverrideOutput.IsValid())
- {
- Output = Inputs.OverrideOutput;
- }
- else
- {
- Output = FScreenPassRenderTarget(SceneColor, ERenderTargetLoadAction::ENoAction);
- }
-
- AddCopyAndFlipTexturePass(GraphBuilder, View, TempTarget.Texture, Output.Texture);
- }
- }
-
- return MoveTemp(Output);
- }
- /** Render graph variant of more advanced DrawScreenPass function. Does *not* clear unused graph
- * resources, since the parameters might be shared between the vertex and pixel shaders.
- */
- template <typename TSetupFunction, typename TPassParameterStruct>
- FORCEINLINE void AddDrawScreenPass(
- FRDGBuilder& GraphBuilder,
- FRDGEventName&& PassName,
- const FViewInfo& View,
- const FScreenPassTextureViewport& OutputViewport,
- const FScreenPassTextureViewport& InputViewport,
- const FScreenPassPipelineState& PipelineState,
- TPassParameterStruct* PassParameterStruct,
- EScreenPassDrawFlags Flags,
- TSetupFunction SetupFunction)
- {
- PipelineState.Validate();
- check(PassParameterStruct);
-
- GraphBuilder.AddPass(
- Forward
(PassName), - PassParameterStruct,
- ERDGPassFlags::Raster,
- [&View, OutputViewport, InputViewport, PipelineState, SetupFunction, Flags] (FRHICommandListImmediate& RHICmdList)
- {
- DrawScreenPass(RHICmdList, View, OutputViewport, InputViewport, PipelineState, Flags, SetupFunction);
- });
- }
-
-
- /** More advanced variant of screen pass drawing. Supports overriding blend / depth stencil
- * pipeline state, and providing a custom vertex shader. Shader parameters are not bound by
- * this method, instead the user provides a setup function that is called prior to draw, but
- * after setting the PSO. This setup function should assign shader parameters.
- */
- template<typename TSetupFunction>
- void DrawScreenPass(
- FRHICommandListImmediate& RHICmdList,
- const FViewInfo& View,
- const FScreenPassTextureViewport& OutputViewport,
- const FScreenPassTextureViewport& InputViewport,
- const FScreenPassPipelineState& PipelineState,
- EScreenPassDrawFlags Flags,
- TSetupFunction SetupFunction)
- {
- PipelineState.Validate();
-
- const FIntRect InputRect = InputViewport.Rect;
- const FIntPoint InputSize = InputViewport.Extent;
- const FIntRect OutputRect = OutputViewport.Rect;
- const FIntPoint OutputSize = OutputRect.Size();
-
- RHICmdList.SetViewport(OutputRect.Min.X, OutputRect.Min.Y, 0.0f, OutputRect.Max.X, OutputRect.Max.Y, 1.0f);
-
- SetScreenPassPipelineState(RHICmdList, PipelineState);
-
- SetupFunction(RHICmdList);
-
- FIntPoint LocalOutputPos(FIntPoint::ZeroValue);
- FIntPoint LocalOutputSize(OutputSize);
- EDrawRectangleFlags DrawRectangleFlags = EDRF_UseTriangleOptimization;
-
- const bool bFlipYAxis = (Flags & EScreenPassDrawFlags::FlipYAxis) == EScreenPassDrawFlags::FlipYAxis;
-
- if (bFlipYAxis)
- {
- // Draw the quad flipped. Requires that the cull mode be disabled.
- LocalOutputPos.Y = OutputSize.Y;
- LocalOutputSize.Y = -OutputSize.Y;
-
- // Triangle optimization currently doesn't work when flipped.
- DrawRectangleFlags = EDRF_Default;
- }
-
- const bool bUseHMDHiddenAreaMask = (Flags & EScreenPassDrawFlags::AllowHMDHiddenAreaMask) == EScreenPassDrawFlags::AllowHMDHiddenAreaMask
- ? View.bHMDHiddenAreaMaskActive
- : false;
-
- DrawPostProcessPass(
- RHICmdList,
- LocalOutputPos.X, LocalOutputPos.Y, LocalOutputSize.X, LocalOutputSize.Y,
- InputRect.Min.X, InputRect.Min.Y, InputRect.Width(), InputRect.Height(),
- OutputSize,
- InputSize,
- PipelineState.VertexShader,
- View.StereoPass,
- bUseHMDHiddenAreaMask,
- DrawRectangleFlags);
- }
- void DrawPostProcessPass(
- FRHICommandList& RHICmdList,
- float X,
- float Y,
- float SizeX,
- float SizeY,
- float U,
- float V,
- float SizeU,
- float SizeV,
- FIntPoint TargetSize,
- FIntPoint TextureSize,
- const TShaderRef
& VertexShader, - EStereoscopicPass StereoView,
- bool bHasCustomMesh,
- EDrawRectangleFlags Flags)
- {
- if (bHasCustomMesh && IStereoRendering::IsStereoEyePass(StereoView))
- {
- DrawHmdMesh(RHICmdList, X, Y, SizeX, SizeY, U, V, SizeU, SizeV, TargetSize, TextureSize, StereoView, VertexShader);
- }
- else
- {
- DrawRectangle(RHICmdList, X, Y, SizeX, SizeY, U, V, SizeU, SizeV, TargetSize, TextureSize, VertexShader, Flags);
- }
- }
-
- void DrawRectangle(
- FRHICommandList& RHICmdList,
- float X,
- float Y,
- float SizeX,
- float SizeY,
- float U,
- float V,
- float SizeU,
- float SizeV,
- FIntPoint TargetSize,
- FIntPoint TextureSize,
- const TShaderRef
& VertexShader, - EDrawRectangleFlags Flags,
- uint32 InstanceCount
- )
- {
- InternalDrawRectangle(RHICmdList, X, Y, SizeX, SizeY, U, V, SizeU, SizeV, TargetSize, TextureSize, VertexShader, Flags, InstanceCount);
- }
-
- template <typename TRHICommandList>
- static inline void InternalDrawRectangle(
- TRHICommandList& RHICmdList,
- float X,
- float Y,
- float SizeX,
- float SizeY,
- float U,
- float V,
- float SizeU,
- float SizeV,
- FIntPoint TargetSize,
- FIntPoint TextureSize,
- const TShaderRef
& VertexShader, - EDrawRectangleFlags Flags,
- uint32 InstanceCount
- )
- {
- float ClipSpaceQuadZ = 0.0f;
-
- DoDrawRectangleFlagOverride(Flags);
-
- // triangle if extending to left and top of the given rectangle, if it's not left top of the viewport it can cause artifacts
- if(X > 0.0f || Y > 0.0f)
- {
- // don't use triangle optimization
- Flags = EDRF_Default;
- }
-
- // Set up vertex uniform parameters for scaling and biasing the rectangle.
- // Note: Use DrawRectangle in the vertex shader to calculate the correct vertex position and uv.
-
- FDrawRectangleParameters Parameters;
- Parameters.PosScaleBias = FVector4(SizeX, SizeY, X, Y);
- Parameters.UVScaleBias = FVector4(SizeU, SizeV, U, V);
-
- Parameters.InvTargetSizeAndTextureSize = FVector4(
- 1.0f / TargetSize.X, 1.0f / TargetSize.Y,
- 1.0f / TextureSize.X, 1.0f / TextureSize.Y);
-
- SetUniformBufferParameterImmediate(RHICmdList, VertexShader.GetVertexShader(), VertexShader->GetUniformBufferParameter
(), Parameters); -
- if(Flags == EDRF_UseTesselatedIndexBuffer)
- {
- // no vertex buffer needed as we compute it in VS
- RHICmdList.SetStreamSource(0, NULL, 0);
-
- RHICmdList.DrawIndexedPrimitive(
- GTesselatedScreenRectangleIndexBuffer.IndexBufferRHI,
- /*BaseVertexIndex=*/ 0,
- /*MinIndex=*/ 0,
- /*NumVertices=*/ GTesselatedScreenRectangleIndexBuffer.NumVertices(),
- /*StartIndex=*/ 0,
- /*NumPrimitives=*/ GTesselatedScreenRectangleIndexBuffer.NumPrimitives(),
- /*NumInstances=*/ InstanceCount
- );
- }
- else
- {
- if (Flags == EDRF_UseTriangleOptimization)
- {
- FPixelShaderUtils::DrawFullscreenTriangle(RHICmdList, InstanceCount);
- }
- else
- {
- FPixelShaderUtils::DrawFullscreenQuad(RHICmdList, InstanceCount);
- }
- }
- }
shader :PostProcessMaterialShaders.usf
- #if NUM_TEX_COORD_INTERPOLATORS
- void GetMaterialCustomizedUVs(FMaterialVertexParameters Parameters, inout float2 OutTexCoords[NUM_TEX_COORD_INTERPOLATORS])
- {
- OutTexCoords[0] = Parameters.TexCoords[0].xy;
-
- }
-
- void GetCustomInterpolators(FMaterialVertexParameters Parameters, inout float2 OutTexCoords[NUM_TEX_COORD_INTERPOLATORS])
- {
-
- }
- #endif
- // Copyright Epic Games, Inc. All Rights Reserved.
-
- /*=============================================================================
- PostProcessMaterialShaders.usf: Shaders for rendering post process materials
- =============================================================================*/
-
- #include "Common.ush"
- #include "ScreenPass.ush"
-
- #ifndef POST_PROCESS_MATERIAL
- #define POST_PROCESS_MATERIAL 0
- #endif
-
- #ifndef POST_PROCESS_MATERIAL_MOBILE
- #define POST_PROCESS_MATERIAL_MOBILE 0
- #endif
-
- #if (POST_PROCESS_MATERIAL == 0)
- #error POST_PROCESS_MATERIAL must be defined to non-zero in the shader compilation environment.
- #endif
-
- #if (FEATURE_LEVEL <= FEATURE_LEVEL_ES3_1) != POST_PROCESS_MATERIAL_MOBILE
- #error POST_PROCESS_MATERIAL_MOBILE define does not match feature level.
- #endif
-
- // Must match ESceneTextureId
- #define PPI_PostProcessInput0 14
- #define PPI_PostProcessInput1 15
- #define PPI_PostProcessInput2 16
- #define PPI_PostProcessInput3 17
- #define PPI_PostProcessInput4 18
-
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessInput_0)
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessInput_1)
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessInput_2)
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessInput_3)
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessInput_4)
- SCREEN_PASS_TEXTURE_VIEWPORT(PostProcessOutput)
-
- Texture2D PostProcessInput_0_Texture;
- Texture2D PostProcessInput_1_Texture;
- Texture2D PostProcessInput_2_Texture;
- Texture2D PostProcessInput_3_Texture;
- Texture2D PostProcessInput_4_Texture;
-
- SamplerState PostProcessInput_0_Sampler;
- SamplerState PostProcessInput_1_Sampler;
- SamplerState PostProcessInput_2_Sampler;
- SamplerState PostProcessInput_3_Sampler;
- SamplerState PostProcessInput_4_Sampler;
- SamplerState PostProcessInput_BilinearSampler;
-
- #if SUPPORTS_INDEPENDENT_SAMPLERS
- #define PostProcessInput_0_SharedSampler PostProcessInput_0_Sampler
- #define PostProcessInput_1_SharedSampler PostProcessInput_0_Sampler
- #define PostProcessInput_2_SharedSampler PostProcessInput_0_Sampler
- #define PostProcessInput_3_SharedSampler PostProcessInput_0_Sampler
- #define PostProcessInput_4_SharedSampler PostProcessInput_0_Sampler
- #else
- #define PostProcessInput_0_SharedSampler PostProcessInput_0_Sampler
- #define PostProcessInput_1_SharedSampler PostProcessInput_1_Sampler
- #define PostProcessInput_2_SharedSampler PostProcessInput_2_Sampler
- #define PostProcessInput_3_SharedSampler PostProcessInput_3_Sampler
- #define PostProcessInput_4_SharedSampler PostProcessInput_4_Sampler
- #endif
-
- #define EYE_ADAPTATION_LOOSE_PARAMETERS 1
-
- #include "/Engine/Generated/Material.ush"
-
- struct FPostProcessMaterialVSToPS
- {
- float4 Position : SV_POSITION;
-
- #if NUM_TEX_COORD_INTERPOLATORS
- float4 TexCoords[(NUM_TEX_COORD_INTERPOLATORS+1)/2] : TEXCOORD0;
- #endif
- };
-
- #if NUM_TEX_COORD_INTERPOLATORS
- float2 GetUV(FPostProcessMaterialVSToPS Interpolants, int UVIndex)
- {
- float4 UVVector = Interpolants.TexCoords[UVIndex / 2];
- return Mod(UVIndex, 2) == 1 ? UVVector.zw : UVVector.xy;
- }
-
- void SetUV(inout FPostProcessMaterialVSToPS Interpolants, int UVIndex, float2 InValue)
- {
- FLATTEN
- if (Mod(UVIndex, 2) == 1)
- {
- Interpolants.TexCoords[UVIndex / 2].zw = InValue;
- }
- else
- {
- Interpolants.TexCoords[UVIndex / 2].xy = InValue;
- }
- }
- #endif
-
- FMaterialVertexParameters GetPostProcessMaterialVSParameters(float2 UV)
- {
- // Most params irrelevant so not a lot to fill out here
- FMaterialVertexParameters Result = (FMaterialVertexParameters)0;
- Result.VertexColor = 1.f.xxxx;
- Result.WorldPosition = float3(UV, 0.f);
-
- #if NUM_MATERIAL_TEXCOORDS_VERTEX
- UNROLL
- for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS_VERTEX; CoordinateIndex++)
- {
- Result.TexCoords[CoordinateIndex] = UV;
- }
- #endif
-
- return Result;
- }
-
- #if (FEATURE_LEVEL > FEATURE_LEVEL_ES3_1)
-
- #if VERTEXSHADER
-
- void MainVS(
- in float4 InPosition : ATTRIBUTE0,
- out FPostProcessMaterialVSToPS Output
- )
- {
- Output = (FPostProcessMaterialVSToPS)0;
- DrawRectangle(InPosition, Output.Position);
-
- #if NUM_TEX_COORD_INTERPOLATORS
- FMaterialVertexParameters VertexParameters = GetPostProcessMaterialVSParameters(InPosition.xy);
-
- float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS];
- GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
- GetCustomInterpolators(VertexParameters, CustomizedUVs);
-
- {
- UNROLL
- for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
- {
- SetUV(Output, CoordinateIndex, InPosition.xy);
- }
- }
- {
- UNROLL
- for (int CoordinateIndex = NUM_MATERIAL_TEXCOORDS; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
- {
- SetUV(Output, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
- }
- }
- #endif
- }
-
- void MainVS_VideoOverlay(
- in float4 InPosition : ATTRIBUTE0,
- in float2 InTexCoord : ATTRIBUTE1,
- out float2 OutUV : TEXCOORD0,
- out float4 OutPosition : SV_POSITION
- )
- {
- DrawRectangle(InPosition, InTexCoord, OutPosition, OutUV);
- }
-
- #elif PIXELSHADER
-
- void MainPS(
- in FPostProcessMaterialVSToPS Input,
- out float4 OutColor : SV_Target0
- )
- {
- ResolvedView = ResolveView();
- FMaterialPixelParameters Parameters = MakeInitializedMaterialPixelParameters();
- FPixelMaterialInputs PixelMaterialInputs;
-
- // can be optimized
- float4 SvPosition = Input.Position;
- float2 ViewportUV = (SvPosition.xy - PostProcessOutput_ViewportMin.xy) * PostProcessOutput_ViewportSizeInverse.xy;
-
- #if NUM_TEX_COORD_INTERPOLATORS
- {
- UNROLL
- for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
- {
- Parameters.TexCoords[CoordinateIndex] = ViewportUV;
- }
- }
- {
- UNROLL
- for (int CoordinateIndex = NUM_MATERIAL_TEXCOORDS; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
- {
- Parameters.TexCoords[CoordinateIndex] = GetUV(Input, CoordinateIndex);
- }
- }
- #endif
-
- Parameters.VertexColor = 1;
-
- SvPosition.z = LookupDeviceZ(ViewportUVToBufferUV(ViewportUV));
- SvPosition.z = max(SvPosition.z, 1e-18);
-
- // fill out other related material parameters
- CalcMaterialParametersPost(Parameters, PixelMaterialInputs, SvPosition, true);
-
- // Grab emissive colour as output
- #if MATERIAL_OUTPUT_OPACITY_AS_ALPHA
- const float Alpha = GetMaterialOpacity(PixelMaterialInputs);
- #else
- const float Alpha = 1.0f;
- #endif
- OutColor = float4(GetMaterialEmissive(PixelMaterialInputs), Alpha );
-
- #if !MATERIALBLENDING_MODULATE && USE_PREEXPOSURE && POST_PROCESS_MATERIAL_BEFORE_TONEMAP
- OutColor.xyz *= View.PreExposure;
- #endif
- }
-
- void MainPS_VideoOverlay(
- in float2 InUV : TEXCOORD0,
- in float4 SvPosition : SV_Position, // after all interpolators
- out float4 OutColor : SV_Target0
- )
- {
- ResolvedView = ResolveView();
- FMaterialPixelParameters Parameters = MakeInitializedMaterialPixelParameters();
- FPixelMaterialInputs PixelMaterialInputs;
-
- float2 ViewportUV = InUV;
-
- #if NUM_MATERIAL_TEXCOORDS
- for(int CoordinateIndex = 0;CoordinateIndex < NUM_MATERIAL_TEXCOORDS;CoordinateIndex++)
- {
- Parameters.TexCoords[CoordinateIndex] = ViewportUV;
- }
- #endif
-
- Parameters.VertexColor = 1;
-
- SvPosition.z = LookupDeviceZ(ViewportUVToBufferUV(ViewportUV));
- SvPosition.z = max(SvPosition.z, 1e-18);
-
- // fill out other related material parameters
- CalcMaterialParametersPost(Parameters, PixelMaterialInputs, SvPosition, true);
-
- // Grab emissive colour as output
- #if MATERIAL_OUTPUT_OPACITY_AS_ALPHA
- const float Alpha = GetMaterialOpacity(PixelMaterialInputs);
- #else
- const float Alpha = 1.0f;
- #endif
- OutColor = float4(GetMaterialEmissive(PixelMaterialInputs), Alpha );
- }
-
- #else // !VERTEXSHADER && !PIXELSHADER
- #error Wrong shader domain.
-
- #endif
-
- #else // FEATURE_LEVEL_ES3_1
-
- Texture2D MobileCustomStencilTexture;
- SamplerState MobileCustomStencilTextureSampler;
-
- int MobileStencilValueRef; // Use integer cause it has to be negative to make the less function to pass the test as always
-
- uint bFlipYAxis;
-
- //
- // Mobile version
- //
- void MainVS(
- in float4 InPosition : ATTRIBUTE0,
- in float2 InTexCoord : ATTRIBUTE1,
- out FPostProcessMaterialVSToPS Output
- )
- {
- Output = (FPostProcessMaterialVSToPS)0;
- float2 OutUV;
- DrawRectangle(InPosition, InTexCoord, Output.Position, OutUV);
-
- #if NUM_TEX_COORD_INTERPOLATORS
- FMaterialVertexParameters VertexParameters = GetPostProcessMaterialVSParameters(InPosition.xy);
-
- float2 CustomizedUVs[NUM_TEX_COORD_INTERPOLATORS];
- GetMaterialCustomizedUVs(VertexParameters, CustomizedUVs);
- GetCustomInterpolators(VertexParameters, CustomizedUVs);
-
- UNROLL
- for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
- {
- #if POST_PROCESS_AR_PASSTHROUGH
- SetUV(Output, CoordinateIndex, OutUV);
- #else
- SetUV(Output, CoordinateIndex, InPosition.xy);
- #endif
- }
- UNROLL
- for (int CoordinateIndex = NUM_MATERIAL_TEXCOORDS; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
- {
- SetUV(Output, CoordinateIndex, CustomizedUVs[CoordinateIndex]);
- }
- #endif
- }
-
- #define MOBILE_STENCIL_COMPARE_LESS 0
- #define MOBILE_STENCIL_COMPARE_LESSEQUAL 1
- #define MOBILE_STENCIL_COMPARE_GREATE 2
- #define MOBILE_STENCIL_COMPARE_GREATEEQUAL 3
- #define MOBILE_STENCIL_COMPARE_EQUAL 4
- #define MOBILE_STENCIL_COMPARE_NOTEQUAL 5
- #define MOBILE_STENCIL_COMPARE_NEVER 6
- #define MOBILE_STENCIL_COMPARE_ALWAYS 7
-
- #ifndef MOBILE_STENCIL_COMPARE_FUNCTION
- #define MOBILE_STENCIL_COMPARE_FUNCTION MOBILE_STENCIL_COMPARE_NEVER
- #endif
-
- void MainPS(
- in FPostProcessMaterialVSToPS Input,
- out half4 OutColor : SV_Target0
- )
- {
- ResolvedView = ResolveView();
- FMaterialPixelParameters Parameters = MakeInitializedMaterialPixelParameters();
- FPixelMaterialInputs PixelMaterialInputs;
-
- // can be optimized
- float4 SvPosition = Input.Position;
- if (bFlipYAxis)
- {
- SvPosition.y = PostProcessOutput_ViewportSize.y - SvPosition.y;
- }
- float2 ViewportUV = (SvPosition - PostProcessOutput_ViewportMin) * PostProcessOutput_ViewportSizeInverse;
- float2 BufferUV = ViewportUVToBufferUV(ViewportUV);
-
- #if NUM_TEX_COORD_INTERPOLATORS
- UNROLL
- for (int CoordinateIndex = 0; CoordinateIndex < NUM_MATERIAL_TEXCOORDS; CoordinateIndex++)
- {
- #if POST_PROCESS_AR_PASSTHROUGH
- Parameters.TexCoords[CoordinateIndex] = GetUV(Input, CoordinateIndex);
- #else
- Parameters.TexCoords[CoordinateIndex] = ViewportUV;
- #endif
- }
- UNROLL
- for (int CoordinateIndex = NUM_MATERIAL_TEXCOORDS; CoordinateIndex < NUM_TEX_COORD_INTERPOLATORS; CoordinateIndex++)
- {
- Parameters.TexCoords[CoordinateIndex] = GetUV(Input, CoordinateIndex);
- }
- #endif
- Parameters.VertexColor = 1;
-
- float ClipValue = 1.0f;
-
- #if MOBILE_STENCIL_COMPARE_FUNCTION != MOBILE_STENCIL_COMPARE_NEVER && MOBILE_STENCIL_COMPARE_FUNCTION != MOBILE_STENCIL_COMPARE_ALWAYS
- int MobileStencilValue = floor(Texture2DSample(MobileCustomStencilTexture, MobileCustomStencilTextureSampler, BufferUV).r*255.0f + 0.5f);
- #endif
-
- #if MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_LESS
- ClipValue = MobileStencilValueRef < MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_LESSEQUAL
- ClipValue = MobileStencilValueRef <= MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_GREATE
- ClipValue = MobileStencilValueRef > MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_GREATEEQUAL
- ClipValue = MobileStencilValueRef >= MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_EQUAL
- ClipValue = MobileStencilValueRef == MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_NOTEQUAL
- ClipValue = MobileStencilValueRef != MobileStencilValue ? 1.0f : -1.0f;
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_NEVER
- #elif MOBILE_STENCIL_COMPARE_FUNCTION == MOBILE_STENCIL_COMPARE_ALWAYS
- ClipValue = MobileStencilValueRef == 256 ? 1.0f : -1.0f;
- #endif
-
- #if MOBILE_STENCIL_COMPARE_FUNCTION != MOBILE_STENCIL_COMPARE_NEVER
- clip(ClipValue);
- #endif
-
- float DeviceZ = LookupDeviceZ(BufferUV);
- SvPosition.z = DeviceZ;
- SvPosition.z = max(SvPosition.z, 1e-18);
- // fill out other related material parameters
- CalcMaterialParametersPost(Parameters, PixelMaterialInputs, SvPosition, true);
-
- // Grab emissive colour as output
- half3 EmissiveColor = GetMaterialEmissive(PixelMaterialInputs);
-
- #if MATERIAL_OUTPUT_OPACITY_AS_ALPHA
- half Alpha = GetMaterialOpacity(PixelMaterialInputs);
- #else
- half Alpha = Parameters.BackupSceneColorAlpha;
- #endif
- half4 FullSceneColor = half4(EmissiveColor, Alpha);
-
- #if POST_PROCESS_MATERIAL_BEFORE_TONEMAP
- #if OUTPUT_GAMMA_SPACE
- FullSceneColor.rgb = sqrt(FullSceneColor.rgb);
- #endif
-
- #if !MATERIALBLENDING_MODULATE && USE_PREEXPOSURE
- FullSceneColor.xyz *= View.PreExposure;
- #endif
- #endif
- OutColor = FullSceneColor;
- }
- #endif //(FEATURE_LEVEL > FEATURE_LEVEL_ES3_1)