You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden
#rb None
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3156770 on 2016/10/10 by Allan.Bentham
Fix VULKAN_ENABLE_API_DUMP build on android.
Change 3157838 on 2016/10/11 by Allan.Bentham
Fix Vulkan API tracing on android.
Change 3170713 on 2016/10/21 by Steve.Cano
Adding the "Optional Mobile Features BP Library" plugin to explose Blueprint functions for Sound Volume, Battery level, system temperature (only available on android), and Headphones being plugged in
#jira UE-30896
#android
#ios
#ue4
Change 3171064 on 2016/10/21 by Steve.Cano
Plugins to provide a common interface and Android implemenation for providing access to GPS / Location data from Blueprints
#ue4
#android
#jira UE-35917
Change 3171065 on 2016/10/21 by Steve.Cano
IOS implementation of LocationServices plugin to provide access to location data in Blueprints
#ue4
#ios
#jira UE-35917
Change 3181802 on 2016/11/01 by Steve.Cano
Fix an issue introduced in CL 3170713 - Adding new config section to RequiredSections list so that we can generate projects successfully.
#jira UE-30896
#ios
Change 3181807 on 2016/11/01 by Steve.Cano
Make sure to clear out references to our eglSurface when we destroy it, else we will try to set our context with an invalid surface.
#jira UE-35004
#android
#ue4
Change 3184827 on 2016/11/03 by Allan.Bentham
Do not HDR32 encode for views without view family.
TranslucentAlphaOnly blend mode now works with encoding.
#jira UE-37951
Change 3186684 on 2016/11/04 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3188693 on 2016/11/07 by Chris.Babcock
Corrections to memory stats for Android
#jira WEX-3760
#ue4
#android
Change 3191538 on 2016/11/09 by Allan.Bentham
Mobile tonemapper can use CVarTonemapperOverride
Change 3192575 on 2016/11/09 by Chris.Babcock
Support placing UE4Game files in ExternalFilesDir for automatic cleanup on uninstall for distribution packages
#jira UEPLAT-1422
#ue4
#android
Change 3196231 on 2016/11/13 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3196538 on 2016/11/14 by Jack.Porter
Fix issue where lighting would not build for the first editor session of projects defaulting to MobileHDR=false as HardwareTargetingModule didn't set cvars
#jira UE-38507
Change 3198068 on 2016/11/15 by Dmitriy.Dyomin
Fixed android console command sender to work with ADB version 1.0.36
#jira UE-35171
Change 3200230 on 2016/11/16 by Jack.Porter
Remove mosaic resolution limitation on ES3 devices
#jira WEX-3119
Change 3201251 on 2016/11/16 by Chris.Babcock
Fix Android compile error
Change 3203542 on 2016/11/18 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3205598 on 2016/11/21 by Dmitriy.Dyomin
Fixed: Missing selection outline in editor ES2 preview
#jira UE-6458
Change 3205622 on 2016/11/21 by Dmitriy.Dyomin
Fix ES2 build error from CL# 3205598
Change 3207232 on 2016/11/22 by Dmitriy.Dyomin
ES2 GLSL generated shader simplifications
Change 3208608 on 2016/11/23 by Dmitriy.Dyomin
Fixed: Landscape Grasstype warning causes log spam when landscape is streamed in or out
#jira UE-38694
Change 3209135 on 2016/11/23 by Alicia.Cano
Packaging for iOS fails due to several invalid object type errors
#jira UE-38431
#ios
Change 3209822 on 2016/11/24 by Jack.Porter
IWYU changes for LocationServicesBPLibrary
Change 3209824 on 2016/11/24 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3210264 on 2016/11/25 by Jack.Porter
Fix unicode compile issue on Korean windows
Change 3210268 on 2016/11/25 by Jack.Porter
IWYU and unicode fixes to Dev-Mobile
Change 3211800 on 2016/11/28 by Allan.Bentham
Create and set PrimitiveSceneProxy->PrimitiveSceneInfo before SetTransform render thread command is enqueued. Avoids race condition with FPrimitiveSceneInfo's constructor which can occur on out-of-order CPUs.
Change 3212621 on 2016/11/28 by Jack.Porter
More IWYU fixes.
Change 3213080 on 2016/11/29 by Allan.Bentham
enable UseSingleSampleShadowFromStationaryLights on mobile.
PR #2990: Fixes single sample shadows for mobile. (Contributed by kallehamalainen)
Change 3213164 on 2016/11/29 by Jack.Porter
Win32 IWYU fix
Change 3213932 on 2016/11/29 by Chris.Babcock
Fix handling of ETC2 filtering by Google Play Store (if only ETC2, require ES3.0+ but don't use texture filtering in manifest)
#jira UE-39120
#ue4
#android
Change 3214563 on 2016/11/29 by Dmitriy.Dyomin
Disable dynamic buffer discarding on Adreno330 (was casuing 10ms stalls on slate buffers update)
Change 3214571 on 2016/11/29 by Dmitriy.Dyomin
Custom stencil on Mobile
#jira UEMOB-183
Change 3214641 on 2016/11/30 by Dmitriy.Dyomin
Disable distance culling when rendering image for world composition
#jira UE-37754
Change 3214656 on 2016/11/30 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3218479 on 2016/12/01 by Jack.Porter
Fix for Vulkan build error when using AutoSDK
Change 3218596 on 2016/12/02 by Dmitriy.Dyomin
Fixed: Android split screen multiplayer does not function or render correctly
#jira UE-35204
Change 3218874 on 2016/12/02 by Allan.Bentham
Fix CSM shadow bug when ES3.1 + mobileHDR == false.
Fix inverted culling when rendering shadow depths with mobilehdr == false
#jira UE-39111
Change 3220911 on 2016/12/04 by Jack.Porter
Fixed landscape duplicated GUID detection and crash when one of the landscapes is in a hidden streaming level
Change 3220935 on 2016/12/04 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3222831 on 2016/12/05 by Dmitriy.Dyomin
Added support for MGD and Andreno profilers
#jira UEMOB-184
Change 3222843 on 2016/12/05 by Jack.Porter
Fixed bug caused by CL 3196538 causing r.MobileHDR to toggle and crash when opening render settings
#jira UE-38507
Change 3222934 on 2016/12/06 by Jack.Porter
Android graphics debugger text changes
Change 3223042 on 2016/12/06 by Dmitriy.Dyomin
Fixed: missing GPU particles in LDR mode on device
#jira UE-39363
Change 3223043 on 2016/12/06 by Jack.Porter
Fixed logspam warnings from TcpMessaging launching on Android
#jira UE-37895
Change 3223046 on 2016/12/06 by Allan.Bentham
Move ES3.1 preview mode out of experimental.
Add per device quality level preview to ES3.1 preview sub menu when project settings allow.
#jira UEMOB-178
Change 3223113 on 2016/12/06 by Allan.Bentham
changed MOBILE_EMULATION define for METAL_PROFILE on mac. fixes issues with editor primitive rendering with ES3.1 feature level preview.
added -featureleveles2/31 commandline support to metalrhi.
Change 3223117 on 2016/12/06 by Allan.Bentham
Initialise FPrimitiveSceneInfo::CachedReflectionCaptureProxies
Change 3223131 on 2016/12/06 by Allan.Bentham
Fix translucency rendering when mobilehdr == false. (Disable mod shadows when mobilehdr == false.)
#jira UE-38343
Change 3223162 on 2016/12/06 by Jack.Porter
Disallow Absolute World Position with "excluding shader offset" on ES2
#jra UE-25555
Change 3223204 on 2016/12/06 by Jack.Porter
Fix for unable to save levels when landscape components with tessellation moved to another level
#jira UE-39372
Change 3223677 on 2016/12/06 by Chris.Babcock
Fix tabs
Change 3224139 on 2016/12/06 by Chris.Babcock
Support modification of build.xml and add post import additions to GameActivity
#jira UE-31372
#PR #2440
#ue4
#android
Change 3224152 on 2016/12/06 by Chris.Babcock
Add support for MadCatz C.T.R.L.R Android controller models
#ue4
#android
Change 3224162 on 2016/12/06 by Chris.Babcock
Driver bug fix and using separate context for MediaPlayer14 (contributed by BrianHarris)
#jira UE-35825
#PR #2787
#ue4
#android
Change 3224581 on 2016/12/07 by Dmitriy.Dyomin
Fixed black screen regression on iOS OpenGL
Also now reporting shader compiler errors in iOS
Change 3224589 on 2016/12/07 by Allan.Bentham
Increase mobile renderer's maximum CSM cascade limit to 4 and introduce max shadow cascade cvar for mobile which defaults to 2 retaining existing behaviour.
#jira UEMOB-187
Change 3224774 on 2016/12/07 by Jack.Porter
Added flags for mobile shader permutation reduction
Renamed mobile lighting policies to better describe them
Set flags to remove policies not used by SunTemple - saves 22MB package size on Android
#jira: UEMOB-179
Change 3224782 on 2016/12/07 by Allan.Bentham
Add project option to set maximum supported CSM cascades to mobile renderer.
#jira UEMOB-187
Change 3224943 on 2016/12/07 by Dmitriy.Dyomin
Metal iOS will use sRGB textures
#jira UEMOB-189
Change 3225098 on 2016/12/07 by Dmitriy.Dyomin
fix for compile error from 3224943
Change 3225188 on 2016/12/07 by Chris.Babcock
Fix #includes in deferred Android OpenGL
#jira UE-39440
#ue4
#android
Change 3226402 on 2016/12/07 by Dmitriy.Dyomin
Fixed: wrong condition for r8 srgb on mac
#jira UE-39471
Change 3226485 on 2016/12/08 by Dmitriy.Dyomin
Fixed: Rendering Artifacts and invisible objects in Fortnite
regression from nobile custom stencil changes
#jira UE-39452, UE-39455
Change 3226637 on 2016/12/08 by Dmitriy.Dyomin
Fixed: Odin Ensure Texture passed to ClearDepthStencil is not what is currently set as RenderTarget
#jira UE-39482
Change 3226922 on 2016/12/08 by Jack.Porter
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
Change 3227353 on 2016/12/08 by Chris.Babcock
Remove CopyVisualizers batch call again
Change 3228013 on 2016/12/08 By Chris.Babcock
Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)
[CL 3228374 by Jack Porter in Main branch]
2857 lines
94 KiB
C++
2857 lines
94 KiB
C++
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
PostProcessMobile.cpp: Uber post for mobile implementation.
|
|
=============================================================================*/
|
|
|
|
#include "PostProcess/PostProcessMobile.h"
|
|
#include "StaticBoundShaderState.h"
|
|
#include "SceneUtils.h"
|
|
#include "SceneRenderTargetParameters.h"
|
|
#include "SceneRendering.h"
|
|
#include "ScenePrivate.h"
|
|
#include "PostProcess/SceneFilterRendering.h"
|
|
#include "PostProcess/PostProcessEyeAdaptation.h"
|
|
|
|
|
|
static EPixelFormat GetHDRPixelFormat()
|
|
{
|
|
// PF_B8G8R8A8 instead of floats for 32bpp hdr encoding.
|
|
return IsMobileHDR32bpp() ? PF_B8G8R8A8 : PF_FloatRGBA;
|
|
}
|
|
|
|
// return Depth of Field Scale if Gaussian DoF mode is active. 0.0f otherwise.
|
|
float GetMobileDepthOfFieldScale(const FViewInfo& View)
|
|
{
|
|
return View.FinalPostProcessSettings.DepthOfFieldMethod == DOFM_Gaussian ? View.FinalPostProcessSettings.DepthOfFieldScale : 0.0f;
|
|
}
|
|
|
|
//
|
|
// BLOOM SETUP
|
|
//
|
|
|
|
class FPostProcessBloomSetupVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomSetupVS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessBloomSetupVS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessBloomSetupVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
template <uint32 UseSunDof> // 0=none, 1=dof, 2=sun, 3=sun&dof, 4=msaa
|
|
class FPostProcessBloomSetupPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomSetupPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
|
|
//Need to hack in exposure scale for < SM5
|
|
OutEnvironment.SetDefine(TEXT("NO_EYEADAPTATION_EXPOSURE_FIX"), 1);
|
|
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_MSAA"), (UseSunDof & 4) ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_SUN"), (UseSunDof & 2) ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_DOF"), (UseSunDof & 1) ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessBloomSetupPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter BloomThreshold;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessBloomSetupPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
BloomThreshold.Bind(Initializer.ParameterMap, TEXT("BloomThreshold"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI());
|
|
|
|
float ExposureScale = FRCPassPostProcessEyeAdaptation::ComputeExposureScaleValue(Context.View);
|
|
|
|
FVector4 BloomThresholdValue(Settings.BloomThreshold, 0, 0, ExposureScale);
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomThreshold, BloomThresholdValue);
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << BloomThreshold;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomSetupVS_ES2,TEXT("PostProcessMobile"),TEXT("BloomVS_ES2"),SF_Vertex);
|
|
|
|
typedef FPostProcessBloomSetupPS_ES2<0> FPostProcessBloomSetupPS_ES2_0;
|
|
typedef FPostProcessBloomSetupPS_ES2<1> FPostProcessBloomSetupPS_ES2_1;
|
|
typedef FPostProcessBloomSetupPS_ES2<2> FPostProcessBloomSetupPS_ES2_2;
|
|
typedef FPostProcessBloomSetupPS_ES2<3> FPostProcessBloomSetupPS_ES2_3;
|
|
typedef FPostProcessBloomSetupPS_ES2<4> FPostProcessBloomSetupPS_ES2_4;
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessBloomSetupPS_ES2_0,TEXT("PostProcessMobile"),TEXT("BloomPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessBloomSetupPS_ES2_1,TEXT("PostProcessMobile"),TEXT("BloomPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessBloomSetupPS_ES2_2,TEXT("PostProcessMobile"),TEXT("BloomPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessBloomSetupPS_ES2_3,TEXT("PostProcessMobile"),TEXT("BloomPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessBloomSetupPS_ES2_4,TEXT("PostProcessMobile"),TEXT("BloomPS_ES2"),SF_Pixel);
|
|
|
|
template <uint32 UseSunDof>
|
|
static void BloomSetup_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessBloomSetupVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessBloomSetupPS_ES2<UseSunDof> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessBloomSetupES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FSceneView& View = Context.View;
|
|
uint32 UseSun = Context.View.bLightShaftUse ? 1 : 0;
|
|
uint32 UseDof = (GetMobileDepthOfFieldScale(Context.View) > 0.0f) ? 1 : 0;
|
|
uint32 UseSunDof = (UseSun << 1) + UseDof;
|
|
|
|
static const auto CVarMobileMSAA = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileMSAA"));
|
|
const EShaderPlatform ShaderPlatform = GShaderPlatformForFeatureLevel[Context.GetFeatureLevel()];
|
|
UseSunDof += (GSupportsShaderFramebufferFetch && (ShaderPlatform == SP_METAL || IsVulkanMobilePlatform(ShaderPlatform))) ? (CVarMobileMSAA ? (CVarMobileMSAA->GetValueOnRenderThread() > 1 ? 4 : 0) : 0) : 0;
|
|
|
|
switch(UseSunDof)
|
|
{
|
|
case 0: BloomSetup_SetShader<0>(Context); break;
|
|
case 1: BloomSetup_SetShader<1>(Context); break;
|
|
case 2: BloomSetup_SetShader<2>(Context); break;
|
|
case 3: BloomSetup_SetShader<3>(Context); break;
|
|
case 4: BloomSetup_SetShader<4>(Context); break;
|
|
}
|
|
}
|
|
|
|
void FRCPassPostProcessBloomSetupES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessBloomSetup);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
FIntPoint PrePostSourceViewportSize = PrePostSourceViewportRect.Size();
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
FIntPoint DstSize = PrePostSourceViewportSize / 4;
|
|
|
|
FIntPoint SrcSize;
|
|
FIntRect SrcRect;
|
|
if(bUseViewRectSource)
|
|
{
|
|
// Mobile with framebuffer fetch uses view rect as source.
|
|
const FSceneView& View = Context.View;
|
|
SrcSize = InputDesc->Extent;
|
|
// uint32 ScaleFactor = View.ViewRect.Width() / SrcSize.X;
|
|
// SrcRect = View.ViewRect / ScaleFactor;
|
|
// TODO: This won't work with scaled views.
|
|
SrcRect = PrePostSourceViewportRect;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise using exact size texture.
|
|
SrcSize = DstSize;
|
|
SrcRect = DstRect;
|
|
}
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
TShaderMapRef<FPostProcessBloomSetupVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
DstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessBloomSetupES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportRect.Width() / 4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportRect.Height() / 4);
|
|
Ret.DebugName = TEXT("BloomSetup");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// BLOOM SETUP SMALL (BLOOM)
|
|
//
|
|
|
|
class FPostProcessBloomSetupSmallVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomSetupSmallVS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessBloomSetupSmallVS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessBloomSetupSmallVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
class FPostProcessBloomSetupSmallPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomSetupSmallPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessBloomSetupSmallPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter BloomThreshold;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessBloomSetupSmallPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
BloomThreshold.Bind(Initializer.ParameterMap, TEXT("BloomThreshold"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
float ExposureScale = FRCPassPostProcessEyeAdaptation::ComputeExposureScaleValue(Context.View);
|
|
|
|
FVector4 BloomThresholdValue(Settings.BloomThreshold, 0, 0, ExposureScale);
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomThreshold, BloomThresholdValue);
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << BloomThreshold;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomSetupSmallVS_ES2,TEXT("PostProcessMobile"),TEXT("BloomSmallVS_ES2"),SF_Vertex);
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomSetupSmallPS_ES2,TEXT("PostProcessMobile"),TEXT("BloomSmallPS_ES2"),SF_Pixel);
|
|
|
|
|
|
void FRCPassPostProcessBloomSetupSmallES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessBloomSetupSmallVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessBloomSetupSmallPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessBloomSetupSmallES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessBloomSetupSmall);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
FIntPoint DstSize = PrePostSourceViewportSize / 4;
|
|
|
|
FIntPoint SrcSize;
|
|
FIntRect SrcRect;
|
|
if(bUseViewRectSource)
|
|
{
|
|
// Mobile with framebuffer fetch uses view rect as source.
|
|
const FSceneView& View = Context.View;
|
|
SrcSize = InputDesc->Extent;
|
|
// uint32 ScaleFactor = View.ViewRect.Width() / SrcSize.X;
|
|
// SrcRect = View.ViewRect / ScaleFactor;
|
|
// TODO: This won't work with scaled views.
|
|
SrcRect = View.ViewRect;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise using exact size texture.
|
|
SrcSize = DstSize;
|
|
SrcRect = DstRect;
|
|
}
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
TShaderMapRef<FPostProcessBloomSetupSmallVS_ES2> VertexShader(Context.GetShaderMap());
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
DstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessBloomSetupSmallES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("BloomSetupSmall");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// BLOOM DOWNSAMPLE
|
|
//
|
|
|
|
class FPostProcessBloomDownPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomDownPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessBloomDownPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessBloomDownPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomDownPS_ES2,TEXT("PostProcessMobile"),TEXT("BloomDownPS_ES2"),SF_Pixel);
|
|
|
|
|
|
class FPostProcessBloomDownVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomDownVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessBloomDownVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter BloomDownScale;
|
|
|
|
FPostProcessBloomDownVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
BloomDownScale.Bind(Initializer.ParameterMap, TEXT("BloomDownScale"));
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context, float InScale)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomDownScale, InScale);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << BloomDownScale;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomDownVS_ES2,TEXT("PostProcessMobile"),TEXT("BloomDownVS_ES2"),SF_Vertex);
|
|
|
|
|
|
void FRCPassPostProcessBloomDownES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessBloomDown);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
TShaderMapRef<FPostProcessBloomDownVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessBloomDownPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context, Scale);
|
|
PixelShader->SetPS(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize/2;
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessBloomDownES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
Ret.DebugName = TEXT("BloomDown");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// BLOOM UPSAMPLE
|
|
//
|
|
|
|
class FPostProcessBloomUpPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomUpPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessBloomUpPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter TintA;
|
|
FShaderParameter TintB;
|
|
|
|
FPostProcessBloomUpPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
TintA.Bind(Initializer.ParameterMap, TEXT("BloomTintA"));
|
|
TintB.Bind(Initializer.ParameterMap, TEXT("BloomTintB"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context, FVector4& InTintA, FVector4& InTintB)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, TintA, InTintA);
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, TintB, InTintB);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << TintA << TintB;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomUpPS_ES2,TEXT("PostProcessMobile"),TEXT("BloomUpPS_ES2"),SF_Pixel);
|
|
|
|
|
|
class FPostProcessBloomUpVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessBloomUpVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessBloomUpVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter BloomUpScales;
|
|
|
|
FPostProcessBloomUpVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
BloomUpScales.Bind(Initializer.ParameterMap, TEXT("BloomUpScales"));
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context, FVector2D InScale)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomUpScales, InScale);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << BloomUpScales;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessBloomUpVS_ES2,TEXT("PostProcessMobile"),TEXT("BloomUpVS_ES2"),SF_Vertex);
|
|
|
|
|
|
void FRCPassPostProcessBloomUpES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessBloomUp);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false, CF_Always>::GetRHI());
|
|
|
|
TShaderMapRef<FPostProcessBloomUpVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessBloomUpPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
// The 1/8 factor is because bloom is using 8 taps in the filter.
|
|
VertexShader->SetVS(Context, FVector2D(ScaleAB.X, ScaleAB.Y));
|
|
FVector4 TintAScaled = TintA * (1.0f/8.0f);
|
|
FVector4 TintBScaled = TintB * (1.0f/8.0f);
|
|
PixelShader->SetPS(Context, TintAScaled, TintBScaled);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize;
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessBloomUpES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y);
|
|
Ret.DebugName = TEXT("BloomUp");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN MASK
|
|
//
|
|
|
|
template <uint32 UseFetchSunDof, bool bUseDepthTexture> // 0=none, 1=dof, 2=sun, 3=sun&dof, {4,5,6,7}=ES2_USE_FETCH, 8=MSAA-pre-resolve
|
|
class FPostProcessSunMaskPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMaskPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_DEPTHTEXTURE"), bUseDepthTexture ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_MSAA"), (UseFetchSunDof & 8) ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_FETCH"), (UseFetchSunDof & 4) ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_SUN"), (UseFetchSunDof & 2) ? (uint32)1 : (uint32)0);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_DOF"), (UseFetchSunDof & 1) ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessSunMaskPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter SunColorApertureDiv2Parameter;
|
|
|
|
FDeferredPixelShaderParameters DeferredParameters;
|
|
|
|
FPostProcessSunMaskPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
SunColorApertureDiv2Parameter.Bind(Initializer.ParameterMap, TEXT("SunColorApertureDiv2"));
|
|
DeferredParameters.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
FVector4 SunColorApertureDiv2;
|
|
SunColorApertureDiv2.X = Context.View.LightShaftColorMask.R;
|
|
SunColorApertureDiv2.Y = Context.View.LightShaftColorMask.G;
|
|
SunColorApertureDiv2.Z = Context.View.LightShaftColorMask.B;
|
|
SunColorApertureDiv2.W = GetMobileDepthOfFieldScale(Context.View) * 0.5f;
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, SunColorApertureDiv2Parameter, SunColorApertureDiv2);
|
|
|
|
DeferredParameters.Set(Context.RHICmdList, ShaderRHI, Context.View);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << SunColorApertureDiv2Parameter << DeferredParameters;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
// #define avoids a lot of code duplication
|
|
#define SUNMASK_PS_ES2(A) typedef FPostProcessSunMaskPS_ES2<A,true> FPostProcessSunMaskPS_ES2_DEPTH_##A; \
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMaskPS_ES2_DEPTH_##A,TEXT("PostProcessMobile"),TEXT("SunMaskPS_ES2"), SF_Pixel); \
|
|
typedef FPostProcessSunMaskPS_ES2<A,false> FPostProcessSunMaskPS_ES2_##A; \
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMaskPS_ES2_##A,TEXT("PostProcessMobile"),TEXT("SunMaskPS_ES2"), SF_Pixel);
|
|
|
|
SUNMASK_PS_ES2(0) SUNMASK_PS_ES2(1) SUNMASK_PS_ES2(2) SUNMASK_PS_ES2(3) SUNMASK_PS_ES2(4)
|
|
SUNMASK_PS_ES2(5) SUNMASK_PS_ES2(6) SUNMASK_PS_ES2(7) SUNMASK_PS_ES2(8)
|
|
|
|
#undef SUNMASK_PS_ES2
|
|
|
|
|
|
class FPostProcessSunMaskVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMaskVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunMaskVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunMaskVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunMaskVS_ES2,TEXT("PostProcessMobile"),TEXT("SunMaskVS_ES2"),SF_Vertex);
|
|
|
|
template <uint32 UseFetchSunDof, bool bUseDepthTexture>
|
|
static void SunMask_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessSunMaskVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunMaskPS_ES2<UseFetchSunDof, bUseDepthTexture> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
template <bool bUseDepthTexture>
|
|
void FRCPassPostProcessSunMaskES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FSceneView& View = Context.View;
|
|
uint32 UseSun = Context.View.bLightShaftUse ? 1 : 0;
|
|
uint32 UseDof = (GetMobileDepthOfFieldScale(Context.View) > 0.0f) ? 1 : 0;
|
|
uint32 UseFetch = GSupportsShaderFramebufferFetch ? 1 : 0;
|
|
uint32 UseFetchSunDof = (UseFetch << 2) + (UseSun << 1) + UseDof;
|
|
|
|
static const auto CVarMobileMSAA = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MobileMSAA"));
|
|
const EShaderPlatform ShaderPlatform = Context.GetShaderPlatform();
|
|
|
|
if ((GSupportsShaderFramebufferFetch && (ShaderPlatform == SP_METAL || IsVulkanMobilePlatform(ShaderPlatform))) && (CVarMobileMSAA ? CVarMobileMSAA->GetValueOnAnyThread() > 1 : false))
|
|
{
|
|
UseFetchSunDof = 8;
|
|
}
|
|
|
|
switch(UseFetchSunDof)
|
|
{
|
|
case 0: SunMask_SetShader<0, bUseDepthTexture>(Context); break;
|
|
case 1: SunMask_SetShader<1, bUseDepthTexture>(Context); break;
|
|
case 2: SunMask_SetShader<2, bUseDepthTexture>(Context); break;
|
|
case 3: SunMask_SetShader<3, bUseDepthTexture>(Context); break;
|
|
case 4: SunMask_SetShader<4, bUseDepthTexture>(Context); break;
|
|
case 5: SunMask_SetShader<5, bUseDepthTexture>(Context); break;
|
|
case 6: SunMask_SetShader<6, bUseDepthTexture>(Context); break;
|
|
case 7: SunMask_SetShader<7, bUseDepthTexture>(Context); break;
|
|
case 8: SunMask_SetShader<8, bUseDepthTexture>(Context); break;
|
|
}
|
|
}
|
|
|
|
void FRCPassPostProcessSunMaskES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunMask);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
FIntPoint DstSize = PrePostSourceViewportSize;
|
|
|
|
FIntPoint SrcSize;
|
|
FIntRect SrcRect;
|
|
const FSceneView& View = Context.View;
|
|
|
|
TShaderMapRef<FPostProcessSunMaskVS_ES2> VertexShader(Context.GetShaderMap());
|
|
if(bOnChip)
|
|
{
|
|
SrcSize = DstSize;
|
|
//SrcRect = DstRect;
|
|
SrcRect = View.ViewRect;
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
if (InputDesc != NULL && InputDesc->Format == PF_FloatR11G11B10)
|
|
{
|
|
SetShader<true>(Context);
|
|
}
|
|
else
|
|
{
|
|
SetShader<false>(Context);
|
|
}
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
DstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
}
|
|
else
|
|
{
|
|
SrcSize = InputDesc->Extent;
|
|
// uint32 ScaleFactor = View.ViewRect.Width() / SrcSize.X;
|
|
// SrcRect = View.ViewRect / ScaleFactor;
|
|
// TODO: This won't work with scaled views.
|
|
SrcRect = View.ViewRect;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EClearColorAndDepth);
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
if (InputDesc != NULL && InputDesc->Format == PF_FloatR11G11B10)
|
|
{
|
|
SetShader<true>(Context);
|
|
}
|
|
else
|
|
{
|
|
SetShader<false>(Context);
|
|
}
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
DstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunMaskES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y);
|
|
Ret.DebugName = TEXT("SunMask");
|
|
Ret.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN ALPHA
|
|
//
|
|
|
|
template<uint32 UseDof>
|
|
class FPostProcessSunAlphaPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunAlphaPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_DOF"), UseDof ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessSunAlphaPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunAlphaPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
typedef FPostProcessSunAlphaPS_ES2<0> FPostProcessSunAlphaPS_ES2_0;
|
|
typedef FPostProcessSunAlphaPS_ES2<1> FPostProcessSunAlphaPS_ES2_1;
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunAlphaPS_ES2_0,TEXT("PostProcessMobile"),TEXT("SunAlphaPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunAlphaPS_ES2_1,TEXT("PostProcessMobile"),TEXT("SunAlphaPS_ES2"),SF_Pixel);
|
|
|
|
class FPostProcessSunAlphaVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunAlphaVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunAlphaVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter LightShaftCenter;
|
|
|
|
FPostProcessSunAlphaVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
LightShaftCenter.Bind(Initializer.ParameterMap, TEXT("LightShaftCenter"));
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, LightShaftCenter, Context.View.LightShaftCenter);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << LightShaftCenter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunAlphaVS_ES2,TEXT("PostProcessMobile"),TEXT("SunAlphaVS_ES2"),SF_Vertex);
|
|
|
|
template <uint32 UseDof>
|
|
static void SunAlpha_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessSunAlphaVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunAlphaPS_ES2<UseDof> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessSunAlphaES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
if(GetMobileDepthOfFieldScale(Context.View))
|
|
{
|
|
SunAlpha_SetShader<1>(Context);
|
|
}
|
|
else
|
|
{
|
|
SunAlpha_SetShader<0>(Context);
|
|
}
|
|
}
|
|
|
|
void FRCPassPostProcessSunAlphaES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunAlpha);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
TShaderMapRef<FPostProcessSunAlphaVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunAlphaES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
// Only need one 8-bit channel as output (but mobile hardware often doesn't support that as a render target format).
|
|
// Highlight compression (tonemapping) was used to keep this in 8-bit.
|
|
Ret.Format = PF_B8G8R8A8;
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("SunAlpha");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN BLUR
|
|
//
|
|
|
|
class FPostProcessSunBlurPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunBlurPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessSunBlurPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunBlurPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunBlurPS_ES2,TEXT("PostProcessMobile"),TEXT("SunBlurPS_ES2"),SF_Pixel);
|
|
|
|
|
|
class FPostProcessSunBlurVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunBlurVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunBlurVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter LightShaftCenter;
|
|
|
|
FPostProcessSunBlurVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
LightShaftCenter.Bind(Initializer.ParameterMap, TEXT("LightShaftCenter"));
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, LightShaftCenter, Context.View.LightShaftCenter);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << LightShaftCenter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunBlurVS_ES2,TEXT("PostProcessMobile"),TEXT("SunBlurVS_ES2"),SF_Vertex);
|
|
|
|
|
|
void FRCPassPostProcessSunBlurES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunBlur);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
TShaderMapRef<FPostProcessSunBlurVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunBlurPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunBlurES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
// Only need one 8-bit channel as output (but mobile hardware often doesn't support that as a render target format).
|
|
// Highlight compression (tonemapping) was used to keep this in 8-bit.
|
|
Ret.Format = PF_B8G8R8A8;
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("SunBlur");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN MERGE
|
|
//
|
|
|
|
template <uint32 UseSunBloom>
|
|
class FPostProcessSunMergePS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMergePS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
CA_SUPPRESS(6313);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_BLOOM"), (UseSunBloom & 1) ? (uint32)1 : (uint32)0);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_SUN"), (UseSunBloom >> 1) ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessSunMergePS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter SunColorVignetteIntensity;
|
|
FShaderParameter VignetteColor;
|
|
FShaderParameter BloomColor;
|
|
|
|
FPostProcessSunMergePS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
SunColorVignetteIntensity.Bind(Initializer.ParameterMap, TEXT("SunColorVignetteIntensity"));
|
|
VignetteColor.Bind(Initializer.ParameterMap, TEXT("VignetteColor"));
|
|
BloomColor.Bind(Initializer.ParameterMap, TEXT("BloomColor"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
FVector4 SunColorVignetteIntensityParam;
|
|
SunColorVignetteIntensityParam.X = Context.View.LightShaftColorApply.R;
|
|
SunColorVignetteIntensityParam.Y = Context.View.LightShaftColorApply.G;
|
|
SunColorVignetteIntensityParam.Z = Context.View.LightShaftColorApply.B;
|
|
SunColorVignetteIntensityParam.W = Settings.VignetteIntensity;
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, SunColorVignetteIntensity, SunColorVignetteIntensityParam);
|
|
|
|
// Scaling Bloom1 by extra factor to match filter area difference between PC default and mobile.
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomColor, Context.View.FinalPostProcessSettings.Bloom1Tint * Context.View.FinalPostProcessSettings.BloomIntensity * 0.5);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << SunColorVignetteIntensity << BloomColor;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
typedef FPostProcessSunMergePS_ES2<0> FPostProcessSunMergePS_ES2_0;
|
|
typedef FPostProcessSunMergePS_ES2<1> FPostProcessSunMergePS_ES2_1;
|
|
typedef FPostProcessSunMergePS_ES2<2> FPostProcessSunMergePS_ES2_2;
|
|
typedef FPostProcessSunMergePS_ES2<3> FPostProcessSunMergePS_ES2_3;
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMergePS_ES2_0,TEXT("PostProcessMobile"),TEXT("SunMergePS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMergePS_ES2_1,TEXT("PostProcessMobile"),TEXT("SunMergePS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMergePS_ES2_2,TEXT("PostProcessMobile"),TEXT("SunMergePS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessSunMergePS_ES2_3,TEXT("PostProcessMobile"),TEXT("SunMergePS_ES2"),SF_Pixel);
|
|
|
|
|
|
class FPostProcessSunMergeVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMergeVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunMergeVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter LightShaftCenter;
|
|
|
|
FPostProcessSunMergeVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
LightShaftCenter.Bind(Initializer.ParameterMap, TEXT("LightShaftCenter"));
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, LightShaftCenter, Context.View.LightShaftCenter);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << LightShaftCenter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunMergeVS_ES2,TEXT("PostProcessMobile"),TEXT("SunMergeVS_ES2"),SF_Vertex);
|
|
|
|
|
|
|
|
template <uint32 UseSunBloom>
|
|
FShader* SunMerge_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessSunMergeVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunMergePS_ES2<UseSunBloom> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
|
|
return *VertexShader;
|
|
}
|
|
|
|
FShader* FRCPassPostProcessSunMergeES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FSceneView& View = Context.View;
|
|
uint32 UseBloom = (View.FinalPostProcessSettings.BloomIntensity > 0.0f) ? 1 : 0;
|
|
uint32 UseSun = Context.View.bLightShaftUse ? 1 : 0;
|
|
uint32 UseSunBloom = UseBloom + (UseSun<<1);
|
|
|
|
switch(UseSunBloom)
|
|
{
|
|
case 0: return SunMerge_SetShader<0>(Context);
|
|
case 1: return SunMerge_SetShader<1>(Context);
|
|
case 2: return SunMerge_SetShader<2>(Context);
|
|
case 3: return SunMerge_SetShader<3>(Context);
|
|
}
|
|
|
|
check(false);
|
|
return NULL;
|
|
}
|
|
|
|
void FRCPassPostProcessSunMergeES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunMerge);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
FShader* VertexShader = SetShader(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
|
|
// Double buffer sun+bloom+vignette composite.
|
|
if(Context.View.AntiAliasingMethod == AAM_TemporalAA)
|
|
{
|
|
FSceneViewState* ViewState = (FSceneViewState*)Context.View.State;
|
|
if(ViewState)
|
|
{
|
|
ViewState->MobileAaBloomSunVignette0 = PassOutputs[0].PooledRenderTarget;
|
|
}
|
|
}
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunMergeES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
// This might not have a valid input texture.
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("SunMerge");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN MERGE SMALL (BLOOM)
|
|
//
|
|
|
|
class FPostProcessSunMergeSmallPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMergeSmallPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessSunMergeSmallPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter SunColorVignetteIntensity;
|
|
FShaderParameter VignetteColor;
|
|
FShaderParameter BloomColor;
|
|
FShaderParameter BloomColor2;
|
|
|
|
FPostProcessSunMergeSmallPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
SunColorVignetteIntensity.Bind(Initializer.ParameterMap, TEXT("SunColorVignetteIntensity"));
|
|
VignetteColor.Bind(Initializer.ParameterMap, TEXT("VignetteColor"));
|
|
BloomColor.Bind(Initializer.ParameterMap, TEXT("BloomColor"));
|
|
BloomColor2.Bind(Initializer.ParameterMap, TEXT("BloomColor2"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
FVector4 SunColorVignetteIntensityParam;
|
|
SunColorVignetteIntensityParam.X = Context.View.LightShaftColorApply.R;
|
|
SunColorVignetteIntensityParam.Y = Context.View.LightShaftColorApply.G;
|
|
SunColorVignetteIntensityParam.Z = Context.View.LightShaftColorApply.B;
|
|
SunColorVignetteIntensityParam.W = Settings.VignetteIntensity;
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, SunColorVignetteIntensity, SunColorVignetteIntensityParam);
|
|
|
|
// Scaling Bloom1 by extra factor to match filter area difference between PC default and mobile.
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomColor, Context.View.FinalPostProcessSettings.Bloom1Tint * Context.View.FinalPostProcessSettings.BloomIntensity * 0.5);
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, BloomColor2, Context.View.FinalPostProcessSettings.Bloom2Tint * Context.View.FinalPostProcessSettings.BloomIntensity);
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << SunColorVignetteIntensity << BloomColor << BloomColor2;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunMergeSmallPS_ES2,TEXT("PostProcessMobile"),TEXT("SunMergeSmallPS_ES2"),SF_Pixel);
|
|
|
|
class FPostProcessSunMergeSmallVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunMergeSmallVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunMergeSmallVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunMergeSmallVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunMergeSmallVS_ES2,TEXT("PostProcessMobile"),TEXT("SunMergeSmallVS_ES2"),SF_Vertex);
|
|
|
|
void FRCPassPostProcessSunMergeSmallES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessSunMergeSmallVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunMergeSmallPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessSunMergeSmallES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunMergeSmall);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
TShaderMapRef<FPostProcessSunMergeSmallVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
|
|
// Double buffer sun+bloom+vignette composite.
|
|
|
|
if (Context.View.AntiAliasingMethod == AAM_TemporalAA)
|
|
{
|
|
FSceneViewState* ViewState = (FSceneViewState*)Context.View.State;
|
|
if(ViewState)
|
|
{
|
|
ViewState->MobileAaBloomSunVignette0 = PassOutputs[0].PooledRenderTarget;
|
|
}
|
|
}
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunMergeSmallES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
// This might not have a valid input texture.
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("SunMergeSmall");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// DOF DOWNSAMPLE
|
|
//
|
|
|
|
class FPostProcessDofDownVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofDownVS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessDofDownVS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessDofDownVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
template<uint32 UseSun>
|
|
class FPostProcessDofDownPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofDownPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_SUN"), UseSun ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessDofDownPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessDofDownPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessDofDownVS_ES2,TEXT("PostProcessMobile"),TEXT("DofDownVS_ES2"),SF_Vertex);
|
|
|
|
typedef FPostProcessDofDownPS_ES2<0> FPostProcessDofDownPS_ES2_0;
|
|
typedef FPostProcessDofDownPS_ES2<1> FPostProcessDofDownPS_ES2_1;
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessDofDownPS_ES2_0,TEXT("PostProcessMobile"),TEXT("DofDownPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessDofDownPS_ES2_1,TEXT("PostProcessMobile"),TEXT("DofDownPS_ES2"),SF_Pixel);
|
|
|
|
template <uint32 UseSun>
|
|
static void DofDown_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessDofDownVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessDofDownPS_ES2<UseSun> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessDofDownES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FSceneView& View = Context.View;
|
|
if(Context.View.bLightShaftUse)
|
|
{
|
|
DofDown_SetShader<1>(Context);
|
|
}
|
|
else
|
|
{
|
|
DofDown_SetShader<0>(Context);
|
|
}
|
|
}
|
|
|
|
void FRCPassPostProcessDofDownES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessDofDown);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
FIntPoint PrePostSourceViewportSize = PrePostSourceViewportRect.Size();
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
FIntPoint DstSize = PrePostSourceViewportSize / 2;
|
|
|
|
FIntPoint SrcSize;
|
|
FIntRect SrcRect;
|
|
if(bUseViewRectSource)
|
|
{
|
|
// Mobile with framebuffer fetch uses view rect as source.
|
|
const FSceneView& View = Context.View;
|
|
SrcSize = InputDesc->Extent;
|
|
// uint32 ScaleFactor = View.ViewRect.Width() / SrcSize.X;
|
|
// SrcRect = View.ViewRect / ScaleFactor;
|
|
// TODO: This won't work with scaled views.
|
|
SrcRect = PrePostSourceViewportRect;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise using exact size texture.
|
|
SrcSize = DstSize;
|
|
SrcRect = DstRect;
|
|
}
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
TShaderMapRef<FPostProcessDofDownVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcRect.Min.X, SrcRect.Min.Y,
|
|
SrcRect.Width(), SrcRect.Height(),
|
|
DstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessDofDownES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
FIntPoint PrePostSourceViewportSize = PrePostSourceViewportRect.Size();
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
Ret.DebugName = TEXT("DofDown");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// DOF NEAR
|
|
//
|
|
|
|
class FPostProcessDofNearVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofNearVS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
/** Default constructor. */
|
|
FPostProcessDofNearVS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
/** Initialization constructor. */
|
|
FPostProcessDofNearVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
// FShader interface.
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
template<uint32 UseSun>
|
|
class FPostProcessDofNearPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofNearPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("ES2_USE_SUN"), UseSun ? (uint32)1 : (uint32)0);
|
|
}
|
|
|
|
FPostProcessDofNearPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessDofNearPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessDofNearVS_ES2,TEXT("PostProcessMobile"),TEXT("DofNearVS_ES2"),SF_Vertex);
|
|
|
|
typedef FPostProcessDofNearPS_ES2<0> FPostProcessDofNearPS_ES2_0;
|
|
typedef FPostProcessDofNearPS_ES2<1> FPostProcessDofNearPS_ES2_1;
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessDofNearPS_ES2_0,TEXT("PostProcessMobile"),TEXT("DofNearPS_ES2"),SF_Pixel);
|
|
IMPLEMENT_SHADER_TYPE(template<>,FPostProcessDofNearPS_ES2_1,TEXT("PostProcessMobile"),TEXT("DofNearPS_ES2"),SF_Pixel);
|
|
|
|
template <uint32 UseSun>
|
|
static void DofNear_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessDofNearVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessDofNearPS_ES2<UseSun> > PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessDofNearES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FSceneView& View = Context.View;
|
|
if(Context.View.bLightShaftUse)
|
|
{
|
|
DofNear_SetShader<1>(Context);
|
|
}
|
|
else
|
|
{
|
|
DofNear_SetShader<0>(Context);
|
|
}
|
|
}
|
|
|
|
void FRCPassPostProcessDofNearES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessDofNear);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
FIntPoint SrcSize = InputDesc->Extent;
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
TShaderMapRef<FPostProcessDofNearVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessDofNearES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
// Only need one 8-bit channel as output (but mobile hardware often doesn't support that as a render target format).
|
|
Ret.Format = PF_B8G8R8A8;
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("DofNear");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// DOF BLUR
|
|
//
|
|
|
|
class FPostProcessDofBlurPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofBlurPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessDofBlurPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessDofBlurPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessDofBlurPS_ES2,TEXT("PostProcessMobile"),TEXT("DofBlurPS_ES2"),SF_Pixel);
|
|
|
|
|
|
class FPostProcessDofBlurVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessDofBlurVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessDofBlurVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessDofBlurVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Point,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessDofBlurVS_ES2,TEXT("PostProcessMobile"),TEXT("DofBlurVS_ES2"),SF_Vertex);
|
|
|
|
|
|
void FRCPassPostProcessDofBlurES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessDofBlur);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
TShaderMapRef<FPostProcessDofBlurVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessDofBlurPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 2;
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessDofBlurES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/2);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/2);
|
|
Ret.DebugName = TEXT("DofBlur");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// SUN AVG
|
|
//
|
|
|
|
class FPostProcessSunAvgPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunAvgPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessSunAvgPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunAvgPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunAvgPS_ES2,TEXT("PostProcessMobile"),TEXT("SunAvgPS_ES2"),SF_Pixel);
|
|
|
|
|
|
|
|
class FPostProcessSunAvgVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessSunAvgVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessSunAvgVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessSunAvgVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessSunAvgVS_ES2,TEXT("PostProcessMobile"),TEXT("SunAvgVS_ES2"),SF_Vertex);
|
|
|
|
|
|
|
|
static void SunAvg_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessSunAvgVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessSunAvgPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessSunAvgES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
SunAvg_SetShader(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessSunAvgES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessSunAvg);
|
|
|
|
uint32 DstX = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
uint32 DstY = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
|
|
FIntRect DstRect;
|
|
DstRect.Min.X = 0;
|
|
DstRect.Min.Y = 0;
|
|
DstRect.Max.X = DstX;
|
|
DstRect.Max.Y = DstY;
|
|
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef());
|
|
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
|
|
Context.SetViewportAndCallRHI(0, 0, 0.0f, DstX, DstY, 1.0f );
|
|
|
|
Context.RHICmdList.SetBlendState(TStaticBlendState<>::GetRHI());
|
|
Context.RHICmdList.SetRasterizerState(TStaticRasterizerState<>::GetRHI());
|
|
Context.RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI());
|
|
|
|
SetShader(Context);
|
|
|
|
FIntPoint SrcDstSize = PrePostSourceViewportSize / 4;
|
|
TShaderMapRef<FPostProcessSunAvgVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
0, 0,
|
|
DstX, DstY,
|
|
0, 0,
|
|
DstX, DstY,
|
|
SrcDstSize,
|
|
SrcDstSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessSunAvgES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = GetHDRPixelFormat();
|
|
Ret.NumSamples = 1;
|
|
Ret.Extent.X = FMath::Max(1, PrePostSourceViewportSize.X/4);
|
|
Ret.Extent.Y = FMath::Max(1, PrePostSourceViewportSize.Y/4);
|
|
Ret.DebugName = TEXT("SunAvg");
|
|
return Ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// MOBILE AA
|
|
//
|
|
|
|
class FPostProcessAaPS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessAaPS_ES2, Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(EShaderPlatform Platform, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Platform, OutEnvironment);
|
|
}
|
|
|
|
FPostProcessAaPS_ES2() {}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
FShaderParameter AaBlendAmount;
|
|
|
|
FPostProcessAaPS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
AaBlendAmount.Bind(Initializer.ParameterMap, TEXT("AaBlendAmount"));
|
|
}
|
|
|
|
void SetPS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader();
|
|
const FPostProcessSettings& Settings = Context.View.FinalPostProcessSettings;
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetPS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
|
|
// Compute the blend factor which decides the trade off between ghosting in motion and flicker when not moving.
|
|
// This works by computing the screen space motion vector of distant point at the center of the screen.
|
|
// This factor will effectively provide an idea of the amount of camera rotation.
|
|
// Higher camera rotation = less blend factor (0.0).
|
|
// Lower or no camera rotation = high blend factor (0.25).
|
|
FSceneViewState* ViewState = (FSceneViewState*)Context.View.State;
|
|
if(ViewState)
|
|
{
|
|
const FViewInfo& View = Context.View;
|
|
|
|
FMatrix Proj = View.ViewMatrices.ComputeProjectionNoAAMatrix();
|
|
FMatrix PrevProj = ViewState->PrevViewMatrices.ComputeProjectionNoAAMatrix();
|
|
|
|
FMatrix ViewProj = ( Context.View.ViewMatrices.GetViewMatrix() * Proj ).GetTransposed();
|
|
FMatrix PrevViewProj = ( ViewState->PrevViewMatrices.GetViewMatrix() * PrevProj ).GetTransposed();
|
|
|
|
double InvViewProj[16];
|
|
Inverse4x4( InvViewProj, (float*)ViewProj.M );
|
|
|
|
const float* p = (float*)PrevViewProj.M;
|
|
|
|
const double cxx = InvViewProj[ 0]; const double cxy = InvViewProj[ 1]; const double cxz = InvViewProj[ 2]; const double cxw = InvViewProj[ 3];
|
|
const double cyx = InvViewProj[ 4]; const double cyy = InvViewProj[ 5]; const double cyz = InvViewProj[ 6]; const double cyw = InvViewProj[ 7];
|
|
const double czx = InvViewProj[ 8]; const double czy = InvViewProj[ 9]; const double czz = InvViewProj[10]; const double czw = InvViewProj[11];
|
|
const double cwx = InvViewProj[12]; const double cwy = InvViewProj[13]; const double cwz = InvViewProj[14]; const double cww = InvViewProj[15];
|
|
|
|
const double pxx = (double)(p[ 0]); const double pxy = (double)(p[ 1]); const double pxz = (double)(p[ 2]); const double pxw = (double)(p[ 3]);
|
|
const double pyx = (double)(p[ 4]); const double pyy = (double)(p[ 5]); const double pyz = (double)(p[ 6]); const double pyw = (double)(p[ 7]);
|
|
const double pwx = (double)(p[12]); const double pwy = (double)(p[13]); const double pwz = (double)(p[14]); const double pww = (double)(p[15]);
|
|
|
|
float CameraMotion0W = (float)(2.0*(cww*pww - cwx*pww + cwy*pww + (cxw - cxx + cxy)*pwx + (cyw - cyx + cyy)*pwy + (czw - czx + czy)*pwz));
|
|
float CameraMotion2Z = (float)(cwy*pww + cwy*pxw + cww*(pww + pxw) - cwx*(pww + pxw) + (cxw - cxx + cxy)*(pwx + pxx) + (cyw - cyx + cyy)*(pwy + pxy) + (czw - czx + czy)*(pwz + pxz));
|
|
float CameraMotion4Z = (float)(cwy*pww + cww*(pww - pyw) - cwy*pyw + cwx*((-pww) + pyw) + (cxw - cxx + cxy)*(pwx - pyx) + (cyw - cyx + cyy)*(pwy - pyy) + (czw - czx + czy)*(pwz - pyz));
|
|
|
|
// Depth surface 0=far, 1=near.
|
|
// This is simplified to compute camera motion with depth = 0.0 (infinitely far away).
|
|
// Camera motion for pixel (in ScreenPos space).
|
|
float ScaleM = 1.0f / CameraMotion0W;
|
|
// Back projection value (projected screen space).
|
|
float BackX = CameraMotion2Z * ScaleM;
|
|
float BackY = CameraMotion4Z * ScaleM;
|
|
|
|
// Start with the distance in screen space.
|
|
float BlendAmount = BackX * BackX + BackY * BackY;
|
|
if(BlendAmount > 0.0f)
|
|
{
|
|
BlendAmount = sqrt(BlendAmount);
|
|
}
|
|
|
|
// Higher numbers truncate anti-aliasing and ghosting faster.
|
|
float BlendEffect = 8.0f;
|
|
BlendAmount = 0.25f - BlendAmount * BlendEffect;
|
|
if(BlendAmount < 0.0f)
|
|
{
|
|
BlendAmount = 0.0f;
|
|
}
|
|
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, AaBlendAmount, BlendAmount);
|
|
}
|
|
else
|
|
{
|
|
float BlendAmount = 0.0;
|
|
SetShaderValue(Context.RHICmdList, ShaderRHI, AaBlendAmount, BlendAmount);
|
|
}
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter << AaBlendAmount;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessAaPS_ES2,TEXT("PostProcessMobile"),TEXT("AaPS_ES2"),SF_Pixel);
|
|
|
|
|
|
|
|
class FPostProcessAaVS_ES2 : public FGlobalShader
|
|
{
|
|
DECLARE_SHADER_TYPE(FPostProcessAaVS_ES2,Global);
|
|
|
|
static bool ShouldCache(EShaderPlatform Platform)
|
|
{
|
|
return !IsConsolePlatform(Platform);
|
|
}
|
|
|
|
FPostProcessAaVS_ES2(){}
|
|
|
|
public:
|
|
FPostProcessPassParameters PostprocessParameter;
|
|
|
|
FPostProcessAaVS_ES2(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
: FGlobalShader(Initializer)
|
|
{
|
|
PostprocessParameter.Bind(Initializer.ParameterMap);
|
|
}
|
|
|
|
void SetVS(const FRenderingCompositePassContext& Context)
|
|
{
|
|
const FVertexShaderRHIParamRef ShaderRHI = GetVertexShader();
|
|
FGlobalShader::SetParameters(Context.RHICmdList, ShaderRHI, Context.View);
|
|
PostprocessParameter.SetVS(ShaderRHI, Context, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI());
|
|
}
|
|
|
|
virtual bool Serialize(FArchive& Ar) override
|
|
{
|
|
bool bShaderHasOutdatedParameters = FGlobalShader::Serialize(Ar);
|
|
Ar << PostprocessParameter;
|
|
return bShaderHasOutdatedParameters;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_SHADER_TYPE(,FPostProcessAaVS_ES2,TEXT("PostProcessMobile"),TEXT("AaVS_ES2"),SF_Vertex);
|
|
|
|
|
|
|
|
static void Aa_SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
TShaderMapRef<FPostProcessAaVS_ES2> VertexShader(Context.GetShaderMap());
|
|
TShaderMapRef<FPostProcessAaPS_ES2> PixelShader(Context.GetShaderMap());
|
|
|
|
static FGlobalBoundShaderState BoundShaderState;
|
|
|
|
|
|
SetGlobalBoundShaderState(Context.RHICmdList, Context.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader);
|
|
|
|
VertexShader->SetVS(Context);
|
|
PixelShader->SetPS(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessAaES2::SetShader(const FRenderingCompositePassContext& Context)
|
|
{
|
|
Aa_SetShader(Context);
|
|
}
|
|
|
|
void FRCPassPostProcessAaES2::Process(FRenderingCompositePassContext& Context)
|
|
{
|
|
SCOPED_DRAW_EVENT(Context.RHICmdList, PostProcessAa);
|
|
|
|
const FPooledRenderTargetDesc* InputDesc = GetInputDesc(ePId_Input0);
|
|
const FSceneRenderTargetItem& DestRenderTarget = PassOutputs[0].RequestSurface(Context);
|
|
const FPooledRenderTargetDesc& OutputDesc = PassOutputs[0].RenderTargetDesc;
|
|
|
|
const FIntPoint& SrcSize = InputDesc->Extent;
|
|
const FIntPoint& DestSize = OutputDesc.Extent;
|
|
|
|
FSceneViewState* ViewState = (FSceneViewState*)Context.View.State;
|
|
if (ViewState)
|
|
{
|
|
// Double buffer input for temporal AA.
|
|
ViewState->MobileAaColor0 = GetInput(ePId_Input0)->GetOutput()->PooledRenderTarget;
|
|
}
|
|
|
|
check(SrcSize == DestSize);
|
|
|
|
SetRenderTarget(Context.RHICmdList, DestRenderTarget.TargetableTexture, FTextureRHIRef(), ESimpleRenderTargetMode::EExistingColorAndDepth);
|
|
|
|
// Full clear to avoid restore
|
|
if (Context.View.StereoPass != eSSP_RIGHT_EYE)
|
|
{
|
|
// is optimized away if possible (RT size=view size, )
|
|
Context.RHICmdList.ClearColorTexture(DestRenderTarget.TargetableTexture, FLinearColor::Black, FIntRect());
|
|
}
|
|
|
|
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());
|
|
|
|
SetShader(Context);
|
|
|
|
const FIntRect& ViewRect = Context.View.UnscaledViewRect; // Simple upscaling, ES2 post process does not currently have a specific upscaling pass.
|
|
float XPos = ViewRect.Min.X;
|
|
float YPos = ViewRect.Min.Y;
|
|
float Width = ViewRect.Width();
|
|
float Height = ViewRect.Height();
|
|
|
|
TShaderMapRef<FPostProcessAaVS_ES2> VertexShader(Context.GetShaderMap());
|
|
|
|
DrawRectangle(
|
|
Context.RHICmdList,
|
|
XPos, YPos,
|
|
Width, Height,
|
|
XPos, YPos,
|
|
Width, Height,
|
|
DestSize,
|
|
SrcSize,
|
|
*VertexShader,
|
|
EDRF_UseTriangleOptimization);
|
|
|
|
Context.RHICmdList.CopyToResolveTarget(DestRenderTarget.TargetableTexture, DestRenderTarget.ShaderResourceTexture, false, FResolveParams());
|
|
|
|
if (FSceneRenderer::ShouldCompositeEditorPrimitives(Context.View))
|
|
{
|
|
FRHICommandListExecutor::GetImmediateCommandList().ImmediateFlush(EImmediateFlushType::WaitForOutstandingTasksOnly);
|
|
// because of the flush it's ok to remove the const, this is not ideal as the flush can cost performance
|
|
FViewInfo& NonConstView = (FViewInfo&)Context.View;
|
|
|
|
// Remove jitter (ensures editor prims are stable.)
|
|
NonConstView.ViewMatrices.HackRemoveTemporalAAProjectionJitter();
|
|
|
|
NonConstView.InitRHIResources();
|
|
}
|
|
}
|
|
|
|
FPooledRenderTargetDesc FRCPassPostProcessAaES2::ComputeOutputDesc(EPassOutputId InPassOutputId) const
|
|
{
|
|
FPooledRenderTargetDesc Ret;
|
|
Ret.Depth = 0;
|
|
Ret.ArraySize = 1;
|
|
Ret.bIsArray = false;
|
|
Ret.NumMips = 1;
|
|
Ret.TargetableFlags = TexCreate_RenderTargetable;
|
|
Ret.bForceSeparateTargetAndShaderResource = false;
|
|
Ret.Format = PF_B8G8R8A8;
|
|
Ret.NumSamples = 1;
|
|
Ret.DebugName = TEXT("Aa");
|
|
Ret.Extent = GetInput(ePId_Input0)->GetOutput()->RenderTargetDesc.Extent;
|
|
Ret.ClearValue = FClearValueBinding(FLinearColor(0, 0, 0, 0));
|
|
return Ret;
|
|
}
|
|
|