2019-01-03 19:16:26 -05:00
|
|
|
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
2014-03-14 14:13:41 -04:00
|
|
|
|
|
|
|
|
/*=============================================================================
|
|
|
|
|
PostProcessSubsurface.cpp: Screenspace subsurface scattering implementation.
|
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
|
|
|
#include "PostProcess/PostProcessSubsurface.h"
|
|
|
|
|
#include "PostProcess/SceneRenderTargets.h"
|
2019-04-01 19:37:48 -04:00
|
|
|
#include "Engine/SubsurfaceProfile.h"
|
|
|
|
|
#include "CanvasTypes.h"
|
|
|
|
|
#include "RenderTargetTemp.h"
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-06 04:43:26 -04:00
|
|
|
ENGINE_API IPooledRenderTarget* GetSubsufaceProfileTexture_RT(FRHICommandListImmediate& RHICmdList);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
TAutoConsoleVariable<int32> CVarSubsurfaceScattering(
|
|
|
|
|
TEXT("r.SubsurfaceScattering"),
|
|
|
|
|
1,
|
|
|
|
|
TEXT(" 0: disabled\n")
|
|
|
|
|
TEXT(" 1: enabled (default)"),
|
|
|
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
2014-09-05 17:48:09 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<float> CVarSSSScale(
|
|
|
|
|
TEXT("r.SSS.Scale"),
|
|
|
|
|
1.0f,
|
|
|
|
|
TEXT("Affects the Screen space subsurface scattering pass")
|
|
|
|
|
TEXT("(use shadingmodel SubsurfaceProfile, get near to the object as the default)\n")
|
|
|
|
|
TEXT("is human skin which only scatters about 1.2cm)\n")
|
|
|
|
|
TEXT(" 0: off (if there is no object on the screen using this pass it should automatically disable the post process pass)\n")
|
|
|
|
|
TEXT("<1: scale scatter radius down (for testing)\n")
|
|
|
|
|
TEXT(" 1: use given radius form the Subsurface scattering asset (default)\n")
|
|
|
|
|
TEXT(">1: scale scatter radius up (for testing)"),
|
|
|
|
|
ECVF_Scalability | ECVF_RenderThreadSafe);
|
2016-02-16 05:48:48 -05:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<int32> CVarSSSHalfRes(
|
|
|
|
|
TEXT("r.SSS.HalfRes"),
|
|
|
|
|
1,
|
|
|
|
|
TEXT(" 0: full quality (not optimized, as reference)\n")
|
|
|
|
|
TEXT(" 1: parts of the algorithm runs in half resolution which is lower quality but faster (default)"),
|
|
|
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
2014-10-16 13:08:38 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<int32> CVarSSSQuality(
|
|
|
|
|
TEXT("r.SSS.Quality"),
|
|
|
|
|
0,
|
|
|
|
|
TEXT("Defines the quality of the recombine pass when using the SubsurfaceScatteringProfile shading model\n")
|
|
|
|
|
TEXT(" 0: low (faster, default)\n")
|
|
|
|
|
TEXT(" 1: high (sharper details but slower)\n")
|
|
|
|
|
TEXT("-1: auto, 1 if TemporalAA is disabled (without TemporalAA the quality is more noticable)"),
|
|
|
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
2014-09-05 17:48:09 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<int32> CVarSSSFilter(
|
|
|
|
|
TEXT("r.SSS.Filter"),
|
|
|
|
|
1,
|
|
|
|
|
TEXT("Defines the filter method for Screenspace Subsurface Scattering feature.\n")
|
|
|
|
|
TEXT(" 0: point filter (useful for testing, could be cleaner)\n")
|
|
|
|
|
TEXT(" 1: bilinear filter"),
|
|
|
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
Copying //UE4/Dev-Rendering to //UE4/Dev-Main (Source: //UE4/Dev-Rendering @ 3091903)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3072947 on 2016/08/01 by Uriel.Doyon
Texture GUIDs are now included in cooked builds, as they are required by the texture streamer to link build data to in game texture.
#review-3072934 @marcus.wassmer
#jira UE-34045
Change 3073301 on 2016/08/02 by Ben.Woodhouse
Fix for large spotlight culling precision issues, reported on UDN by Aaron Jacobs at Double Fine. For a full description, see the UDN post
https://udn.unrealengine.com/questions/305440/shadowed-light-flicker-caused-by-floating-point-pr.html
#jira UE-34052
Change 3073689 on 2016/08/02 by Ben.Woodhouse
Improved skin postprocess - support for full resolution, with diffuse/spec lighting combined into single RGBA (sharing chroma)
Full res lighting gives less temporal AA flickering, sharper diffuse and specular lighting in the surface (since this is now at full resolution), faster postprocessing if using a 64-bit rendertarget (on NV 980Ti).
Checkerboard rendering is controlled via the r.sss.checkerboard cvar. - 0 is off/full res, 1 is checkerboard, 2 is automatic based on scenecolor (non-checkerboard requires 64bit or more rendertarget w/separate alpha)
Tested/profiled on PC, PS4
Change 3074666 on 2016/08/02 by Daniel.Wright
Fixed stationary skylight brightness
Change 3074667 on 2016/08/02 by Daniel.Wright
Fixed r.ReflectionEnvironmentLightmapMixing
Change 3074687 on 2016/08/02 by Daniel.Wright
Disallowed DrawMaterialToRenderTarget and Begin/EndDrawCanvasToRenderTarget in construction scripts, since they don't work in game. Blutilities can be used to do blueprint rendering in the editor.
Change 3075241 on 2016/08/03 by Rolando.Caloca
DR - Fix linux compile issue & static analysis warning
Change 3075746 on 2016/08/03 by Daniel.Wright
Removed bOverride_AntiAliasingMethod and outdated ini references to PP AntiAliasingMethod
Change 3075783 on 2016/08/03 by Ryan.Brucks
#code.review Marcus.Wassmer
Added two material nodes that return Atmospheric Light Vector and Light Direction using:
View.AtmosphericFogSunColor
View.AtmosphericFogSunDirection
Nodes are called:
AtmosphericLightVector
AtmosphericLightColor
Also changed SceneRendering.cpp so that values will be grabbed from directional lights without needing an Atmospheric Fog actor in the scene.
Change 3075969 on 2016/08/03 by Uriel.Doyon
Material GUIDs are not updated anymore when parents or textures change.
Lighting now uses a hash built from the list of parents, textures and shader functions.
#review-3072980 @marcus.wassmer @daniel.wright
Change 3076116 on 2016/08/03 by Ryan.Brucks
#code.review marcus.wassmer
Fixed typo in the Caption of new Nodes "Atmospheric Light Vector" and "Atmospheric Light Color"
Change 3076456 on 2016/08/03 by Rolando.Caloca
DR - Fix geometry shader gl_Layer for SPIR-V
Change 3076730 on 2016/08/03 by Uriel.Doyon
Added user warning logic for the texture streaming build. Ran in MapCheck, BeginPlay and PreSave.
#review-3072984 @marcus.wassmer
Change 3077616 on 2016/08/04 by Daniel.Wright
Planar reflection show flags can now be edited
Change 3077621 on 2016/08/04 by Daniel.Wright
Changed default Planar Reflection DistanceFromPlaneFadeoutEnd from 600 to 100, which reduces artifacts and is a more intuitive initial setting
Change 3077792 on 2016/08/04 by Daniel.Wright
Fixed an unnecessary sky capture caused by the sky light component owned by the default ASkyLight
Change 3077799 on 2016/08/04 by Daniel.Wright
Skip RF_ArchetypeObject for reflection captures
Change 3077876 on 2016/08/04 by Marc.Olano
Noise material perf improvements
Change random number generator for Gradient-ALU (1.7x perf boost), improve speed of Voronoi noise quality level 3.
Removes integer BBS random number generators. Fewer instructions, but too slow to use (see 1.7x perf boost above)
Change 3077884 on 2016/08/04 by Daniel.Wright
Lighting channels can now be edited on components with static mobility, since dynamic lights can still affect them
Change 3078994 on 2016/08/05 by Simon.Tovey
Fix for UE-34241
Scene proxy ptr was being cached during a downcast.
Inside a call to CreateDynamicData, CheckMaterialUsage_Concurrent() was causing the scene proxy to be recreated an so the cached ptr was stale.
I've fixed the immediate issue but recreating the scene proxy here doesn't seem great. Maybe CheckMaterailUsage() should be rethought a bit.
Change 3079162 on 2016/08/05 by Ben.Woodhouse
Fix for jittering in Paper2D. Was caused by override being ignored due to a change in intiialization order for AA settings.
#jira UE-34091
Change 3079613 on 2016/08/05 by Daniel.Wright
New blueprint function ClearRenderTarget2D, which is the only way to set a render target alpha directly
New blueprint function CreateRenderTarget2D
Change 3079708 on 2016/08/05 by Uriel.Doyon
Fixed crash when building texture streaming on some levels.
Change 3079795 on 2016/08/05 by Uriel.Doyon
Fixed issue with instanced static meshes when building texture streaming.
Fixed typo with func "GetNumTextureStreamingPrimitives"
Change 3079806 on 2016/08/05 by Uriel.Doyon
Enabled PerTexture MipBias. The per texture mip bias now resets to 0 when the texture gets required at low resolution.
New scalability setting named "r.Streaming.LimitPoolSizeToVRAM" enabling the PoolSize to be limited the available VRAM
(according to GPoolSizeVRAMPercentage)
#review-3074662 @marcus.wassmer
Change 3082698 on 2016/08/09 by Daniel.Wright
Copy - CreateRenderTarget2D uses a world context object as owner, allows use in a construction script
Change 3082699 on 2016/08/09 by Daniel.Wright
Changed display name for 'Two Sided' shading model to 'Two Sided Foliage' to make it clear what it's intended to be used for
Change 3083909 on 2016/08/10 by Olaf.Piesche
#jira UE-34106
#jira UE-32784
#jira UE-31198
Reset vertex factories on mesh emitters if mesh has been reimported (if mesh package is dirty)
Change 3084645 on 2016/08/10 by Olaf.Piesche
#jira UE-30398
Fix offset added to particle collision locations.
Change 3084709 on 2016/08/10 by Daniel.Wright
Copy - Scene capture alpha is now inverted to match DrawMaterialToRenderTarget, and to allow compositing with existing render target contents
Added CompositeMode to SceneCapture2D, which can be used to addively accumulate or composite instead of the default overwrite behavior
Added bCaptureOnMovement to SceneCapture, which can be disabled so the only source of scene capturing is a manual capture by calling CaptureScene()
Change 3084783 on 2016/08/10 by Rolando.Caloca
DR - Use the first targeted rhi shader platform as the initial RHI to load on Windows
#jira UE-34510
Change 3084958 on 2016/08/10 by Daniel.Wright
Copy - Reverted cl 2938543 "Lightmass now respects owner bHidden, and bCastHiddenShadow" because it did not have backwards compatibility so breaks content using hidden light cards
Change 3086023 on 2016/08/11 by Marcus.Wassmer
Merging //UE4/Dev-Main@3085468 to Dev-Rendering (//UE4/Dev-Rendering)
#test none
Change 3086778 on 2016/08/11 by Ben.Woodhouse
Workaround for fortnite character rendering issue. Enable checkerboard rendering by default until we can fix properly
#jira UE-34561
Change 3087404 on 2016/08/12 by Rolando.Caloca
DR - Upgrade glslang to 1.0.21.1
- Added some more debug output
Change 3087524 on 2016/08/12 by Rolando.Caloca
DR - vk - Fixed StencilRef, fixed size of RHIReadSurfaceFloatData (but still returns dummy data)
Change 3087663 on 2016/08/12 by Rolando.Caloca
DR - vk - Fix for SRGB; support for mip texture views
Change 3087735 on 2016/08/12 by Daniel.Wright
TextureRenderTarget2D's can now be up to 8192^2. Anything over 2048 pops up an 'are you sure' dialog.
Change 3087750 on 2016/08/12 by Rolando.Caloca
DR - vk - Minor renaming in prep for merge
Change 3087813 on 2016/08/12 by Rolando.Caloca
DR - vk - More minor cleanup
Change 3087819 on 2016/08/12 by Chris.Bunner
Check material function input types directly, no need to traverse connected graph.
#jira UE-32134
Change 3087901 on 2016/08/12 by Rolando.Caloca
DR - vk - Fix RT view to use 1 mip
Fix depth buffer component swizzle
Change 3088193 on 2016/08/12 by Daniel.Wright
DFAO and RTDF shadows are enabled in High and Epic scalability settings by default
Change 3088988 on 2016/08/15 by Rolando.Caloca
DR - Add Accessors
Change 3089104 on 2016/08/15 by Olaf.Piesche
#jira UE-34241
Sceneproxy can be nullptr in FDynamicMeshEmitterData::Init if the proxy is being recreated
Change 3089208 on 2016/08/15 by Daniel.Wright
Downsampled separate translucency uses a separate view uniform buffer with correct buffer sizes
* Fixes WorldPosition in downsampled translucency
* View uniform buffer parameters are now cached on the view, to allow recreating the uniform buffer without having to rebuild the entire struct. Currently used by global distance field, downsampled separate translucency.
* Fixed the downsampled translucency depth buffer being full res used together with a smaller color target, now they are both the downsampled res
Change 3089209 on 2016/08/15 by Daniel.Wright
Fixed atmospheric fog on translucency
Change 3089457 on 2016/08/15 by Daniel.Wright
Fixed lighting build failure from UMaterialInstanceDynamic assigned to a mesh that's being exported to Lightmass. The Swarm cache entry is created using the parent's guid, causing multiple MID's with the same parent to acquire a file handle multiple times which fails after the first.
Change 3089549 on 2016/08/15 by Daniel.Wright
UMaterialInterface initializes LightingGuid to something valid - causes UMaterialInstanceDynamic to have a valid LightingGuid so they can be used in lighting builds
Change 3089703 on 2016/08/15 by Daniel.Wright
Custom expression fixup for View.RenderTargetSize
Change 3090546 on 2016/08/16 by Daniel.Wright
Hopeful fix for recycled snapshot view crash
Change 3091202 on 2016/08/16 by Daniel.Wright
Manually clear FViewInfo::CachedViewUniformShaderParameters on creating a snapshot, since memcpy is used to create the snapshot view
[CL 3091931 by Gil Gribb in Main branch]
2016-08-17 11:38:13 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<int32> CVarSSSSampleSet(
|
|
|
|
|
TEXT("r.SSS.SampleSet"),
|
|
|
|
|
2,
|
|
|
|
|
TEXT("Defines how many samples we use for Screenspace Subsurface Scattering feature.\n")
|
|
|
|
|
TEXT(" 0: lowest quality (6*2+1)\n")
|
|
|
|
|
TEXT(" 1: medium quality (9*2+1)\n")
|
|
|
|
|
TEXT(" 2: high quality (13*2+1) (default)"),
|
|
|
|
|
ECVF_RenderThreadSafe | ECVF_Scalability);
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
TAutoConsoleVariable<int32> CVarSSSCheckerboard(
|
|
|
|
|
TEXT("r.SSS.Checkerboard"),
|
|
|
|
|
2,
|
|
|
|
|
TEXT("Enables or disables checkerboard rendering for subsurface profile rendering.\n")
|
|
|
|
|
TEXT("This is necessary if SceneColor does not include a floating point alpha channel (e.g 32-bit formats)\n")
|
|
|
|
|
TEXT(" 0: Disabled (high quality) \n")
|
|
|
|
|
TEXT(" 1: Enabled (low quality). Surface lighting will be at reduced resolution.\n")
|
|
|
|
|
TEXT(" 2: Automatic. Non-checkerboard lighting will be applied if we have a suitable rendertarget format\n"),
|
|
|
|
|
ECVF_RenderThreadSafe);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum class ESubsurfaceMode : uint32
|
|
|
|
|
{
|
|
|
|
|
// Performs a full resolution scattering filter.
|
|
|
|
|
FullRes,
|
|
|
|
|
|
|
|
|
|
// Performs a half resolution scattering filter.
|
|
|
|
|
HalfRes,
|
|
|
|
|
|
|
|
|
|
// Reconstructs lighting, but does not perform scattering.
|
|
|
|
|
Bypass,
|
|
|
|
|
|
|
|
|
|
MAX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Returns the [0, N] clamped value of the 'r.SSS.Scale' CVar.
|
2014-10-15 16:18:43 -04:00
|
|
|
float GetSubsurfaceRadiusScale()
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2014-10-15 16:18:43 -04:00
|
|
|
static const auto CVar = IConsoleManager::Get().FindTConsoleVariableDataFloat(TEXT("r.SSS.Scale"));
|
|
|
|
|
check(CVar);
|
|
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
return FMath::Max(0.0f, CVar->GetValueOnRenderThread());
|
2014-10-15 16:18:43 -04:00
|
|
|
}
|
|
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
// Returns the current subsurface mode required by the current view.
|
|
|
|
|
ESubsurfaceMode GetSubsurfaceModeForView(const FViewInfo& View)
|
Copying //UE4/Dev-Rendering to //UE4/Dev-Main (Source: //UE4/Dev-Rendering @ 3091903)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3072947 on 2016/08/01 by Uriel.Doyon
Texture GUIDs are now included in cooked builds, as they are required by the texture streamer to link build data to in game texture.
#review-3072934 @marcus.wassmer
#jira UE-34045
Change 3073301 on 2016/08/02 by Ben.Woodhouse
Fix for large spotlight culling precision issues, reported on UDN by Aaron Jacobs at Double Fine. For a full description, see the UDN post
https://udn.unrealengine.com/questions/305440/shadowed-light-flicker-caused-by-floating-point-pr.html
#jira UE-34052
Change 3073689 on 2016/08/02 by Ben.Woodhouse
Improved skin postprocess - support for full resolution, with diffuse/spec lighting combined into single RGBA (sharing chroma)
Full res lighting gives less temporal AA flickering, sharper diffuse and specular lighting in the surface (since this is now at full resolution), faster postprocessing if using a 64-bit rendertarget (on NV 980Ti).
Checkerboard rendering is controlled via the r.sss.checkerboard cvar. - 0 is off/full res, 1 is checkerboard, 2 is automatic based on scenecolor (non-checkerboard requires 64bit or more rendertarget w/separate alpha)
Tested/profiled on PC, PS4
Change 3074666 on 2016/08/02 by Daniel.Wright
Fixed stationary skylight brightness
Change 3074667 on 2016/08/02 by Daniel.Wright
Fixed r.ReflectionEnvironmentLightmapMixing
Change 3074687 on 2016/08/02 by Daniel.Wright
Disallowed DrawMaterialToRenderTarget and Begin/EndDrawCanvasToRenderTarget in construction scripts, since they don't work in game. Blutilities can be used to do blueprint rendering in the editor.
Change 3075241 on 2016/08/03 by Rolando.Caloca
DR - Fix linux compile issue & static analysis warning
Change 3075746 on 2016/08/03 by Daniel.Wright
Removed bOverride_AntiAliasingMethod and outdated ini references to PP AntiAliasingMethod
Change 3075783 on 2016/08/03 by Ryan.Brucks
#code.review Marcus.Wassmer
Added two material nodes that return Atmospheric Light Vector and Light Direction using:
View.AtmosphericFogSunColor
View.AtmosphericFogSunDirection
Nodes are called:
AtmosphericLightVector
AtmosphericLightColor
Also changed SceneRendering.cpp so that values will be grabbed from directional lights without needing an Atmospheric Fog actor in the scene.
Change 3075969 on 2016/08/03 by Uriel.Doyon
Material GUIDs are not updated anymore when parents or textures change.
Lighting now uses a hash built from the list of parents, textures and shader functions.
#review-3072980 @marcus.wassmer @daniel.wright
Change 3076116 on 2016/08/03 by Ryan.Brucks
#code.review marcus.wassmer
Fixed typo in the Caption of new Nodes "Atmospheric Light Vector" and "Atmospheric Light Color"
Change 3076456 on 2016/08/03 by Rolando.Caloca
DR - Fix geometry shader gl_Layer for SPIR-V
Change 3076730 on 2016/08/03 by Uriel.Doyon
Added user warning logic for the texture streaming build. Ran in MapCheck, BeginPlay and PreSave.
#review-3072984 @marcus.wassmer
Change 3077616 on 2016/08/04 by Daniel.Wright
Planar reflection show flags can now be edited
Change 3077621 on 2016/08/04 by Daniel.Wright
Changed default Planar Reflection DistanceFromPlaneFadeoutEnd from 600 to 100, which reduces artifacts and is a more intuitive initial setting
Change 3077792 on 2016/08/04 by Daniel.Wright
Fixed an unnecessary sky capture caused by the sky light component owned by the default ASkyLight
Change 3077799 on 2016/08/04 by Daniel.Wright
Skip RF_ArchetypeObject for reflection captures
Change 3077876 on 2016/08/04 by Marc.Olano
Noise material perf improvements
Change random number generator for Gradient-ALU (1.7x perf boost), improve speed of Voronoi noise quality level 3.
Removes integer BBS random number generators. Fewer instructions, but too slow to use (see 1.7x perf boost above)
Change 3077884 on 2016/08/04 by Daniel.Wright
Lighting channels can now be edited on components with static mobility, since dynamic lights can still affect them
Change 3078994 on 2016/08/05 by Simon.Tovey
Fix for UE-34241
Scene proxy ptr was being cached during a downcast.
Inside a call to CreateDynamicData, CheckMaterialUsage_Concurrent() was causing the scene proxy to be recreated an so the cached ptr was stale.
I've fixed the immediate issue but recreating the scene proxy here doesn't seem great. Maybe CheckMaterailUsage() should be rethought a bit.
Change 3079162 on 2016/08/05 by Ben.Woodhouse
Fix for jittering in Paper2D. Was caused by override being ignored due to a change in intiialization order for AA settings.
#jira UE-34091
Change 3079613 on 2016/08/05 by Daniel.Wright
New blueprint function ClearRenderTarget2D, which is the only way to set a render target alpha directly
New blueprint function CreateRenderTarget2D
Change 3079708 on 2016/08/05 by Uriel.Doyon
Fixed crash when building texture streaming on some levels.
Change 3079795 on 2016/08/05 by Uriel.Doyon
Fixed issue with instanced static meshes when building texture streaming.
Fixed typo with func "GetNumTextureStreamingPrimitives"
Change 3079806 on 2016/08/05 by Uriel.Doyon
Enabled PerTexture MipBias. The per texture mip bias now resets to 0 when the texture gets required at low resolution.
New scalability setting named "r.Streaming.LimitPoolSizeToVRAM" enabling the PoolSize to be limited the available VRAM
(according to GPoolSizeVRAMPercentage)
#review-3074662 @marcus.wassmer
Change 3082698 on 2016/08/09 by Daniel.Wright
Copy - CreateRenderTarget2D uses a world context object as owner, allows use in a construction script
Change 3082699 on 2016/08/09 by Daniel.Wright
Changed display name for 'Two Sided' shading model to 'Two Sided Foliage' to make it clear what it's intended to be used for
Change 3083909 on 2016/08/10 by Olaf.Piesche
#jira UE-34106
#jira UE-32784
#jira UE-31198
Reset vertex factories on mesh emitters if mesh has been reimported (if mesh package is dirty)
Change 3084645 on 2016/08/10 by Olaf.Piesche
#jira UE-30398
Fix offset added to particle collision locations.
Change 3084709 on 2016/08/10 by Daniel.Wright
Copy - Scene capture alpha is now inverted to match DrawMaterialToRenderTarget, and to allow compositing with existing render target contents
Added CompositeMode to SceneCapture2D, which can be used to addively accumulate or composite instead of the default overwrite behavior
Added bCaptureOnMovement to SceneCapture, which can be disabled so the only source of scene capturing is a manual capture by calling CaptureScene()
Change 3084783 on 2016/08/10 by Rolando.Caloca
DR - Use the first targeted rhi shader platform as the initial RHI to load on Windows
#jira UE-34510
Change 3084958 on 2016/08/10 by Daniel.Wright
Copy - Reverted cl 2938543 "Lightmass now respects owner bHidden, and bCastHiddenShadow" because it did not have backwards compatibility so breaks content using hidden light cards
Change 3086023 on 2016/08/11 by Marcus.Wassmer
Merging //UE4/Dev-Main@3085468 to Dev-Rendering (//UE4/Dev-Rendering)
#test none
Change 3086778 on 2016/08/11 by Ben.Woodhouse
Workaround for fortnite character rendering issue. Enable checkerboard rendering by default until we can fix properly
#jira UE-34561
Change 3087404 on 2016/08/12 by Rolando.Caloca
DR - Upgrade glslang to 1.0.21.1
- Added some more debug output
Change 3087524 on 2016/08/12 by Rolando.Caloca
DR - vk - Fixed StencilRef, fixed size of RHIReadSurfaceFloatData (but still returns dummy data)
Change 3087663 on 2016/08/12 by Rolando.Caloca
DR - vk - Fix for SRGB; support for mip texture views
Change 3087735 on 2016/08/12 by Daniel.Wright
TextureRenderTarget2D's can now be up to 8192^2. Anything over 2048 pops up an 'are you sure' dialog.
Change 3087750 on 2016/08/12 by Rolando.Caloca
DR - vk - Minor renaming in prep for merge
Change 3087813 on 2016/08/12 by Rolando.Caloca
DR - vk - More minor cleanup
Change 3087819 on 2016/08/12 by Chris.Bunner
Check material function input types directly, no need to traverse connected graph.
#jira UE-32134
Change 3087901 on 2016/08/12 by Rolando.Caloca
DR - vk - Fix RT view to use 1 mip
Fix depth buffer component swizzle
Change 3088193 on 2016/08/12 by Daniel.Wright
DFAO and RTDF shadows are enabled in High and Epic scalability settings by default
Change 3088988 on 2016/08/15 by Rolando.Caloca
DR - Add Accessors
Change 3089104 on 2016/08/15 by Olaf.Piesche
#jira UE-34241
Sceneproxy can be nullptr in FDynamicMeshEmitterData::Init if the proxy is being recreated
Change 3089208 on 2016/08/15 by Daniel.Wright
Downsampled separate translucency uses a separate view uniform buffer with correct buffer sizes
* Fixes WorldPosition in downsampled translucency
* View uniform buffer parameters are now cached on the view, to allow recreating the uniform buffer without having to rebuild the entire struct. Currently used by global distance field, downsampled separate translucency.
* Fixed the downsampled translucency depth buffer being full res used together with a smaller color target, now they are both the downsampled res
Change 3089209 on 2016/08/15 by Daniel.Wright
Fixed atmospheric fog on translucency
Change 3089457 on 2016/08/15 by Daniel.Wright
Fixed lighting build failure from UMaterialInstanceDynamic assigned to a mesh that's being exported to Lightmass. The Swarm cache entry is created using the parent's guid, causing multiple MID's with the same parent to acquire a file handle multiple times which fails after the first.
Change 3089549 on 2016/08/15 by Daniel.Wright
UMaterialInterface initializes LightingGuid to something valid - causes UMaterialInstanceDynamic to have a valid LightingGuid so they can be used in lighting builds
Change 3089703 on 2016/08/15 by Daniel.Wright
Custom expression fixup for View.RenderTargetSize
Change 3090546 on 2016/08/16 by Daniel.Wright
Hopeful fix for recycled snapshot view crash
Change 3091202 on 2016/08/16 by Daniel.Wright
Manually clear FViewInfo::CachedViewUniformShaderParameters on creating a snapshot, since memcpy is used to create the snapshot view
[CL 3091931 by Gil Gribb in Main branch]
2016-08-17 11:38:13 -04:00
|
|
|
{
|
2019-04-01 19:37:48 -04:00
|
|
|
const float Radius = GetSubsurfaceRadiusScale();
|
|
|
|
|
const bool bShowSubsurfaceScattering = Radius > 0 && View.Family->EngineShowFlags.SubsurfaceScattering;
|
|
|
|
|
|
|
|
|
|
if (bShowSubsurfaceScattering)
|
|
|
|
|
{
|
|
|
|
|
const bool bHalfRes = CVarSSSHalfRes.GetValueOnRenderThread() != 0;
|
|
|
|
|
if (bHalfRes)
|
|
|
|
|
{
|
|
|
|
|
return ESubsurfaceMode::HalfRes;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return ESubsurfaceMode::FullRes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return ESubsurfaceMode::Bypass;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
bool IsSubsurfaceEnabled()
|
|
|
|
|
{
|
|
|
|
|
const bool bEnabled = CVarSubsurfaceScattering.GetValueOnAnyThread() != 0;
|
|
|
|
|
const bool bHasScale = CVarSSSScale.GetValueOnAnyThread() > 0.0f;
|
|
|
|
|
return (bEnabled && bHasScale);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsSubsurfaceRequiredForView(const FViewInfo& View)
|
|
|
|
|
{
|
|
|
|
|
const bool bSimpleDynamicLighting = IsAnyForwardShadingEnabled(View.GetShaderPlatform());
|
|
|
|
|
const bool bSubsurfaceEnabled = IsSubsurfaceEnabled();
|
|
|
|
|
const bool bViewHasSubsurfaceMaterials = ((View.ShadingModelMaskInView & GetUseSubsurfaceProfileShadingModelMask()) != 0);
|
|
|
|
|
return (bSubsurfaceEnabled && bViewHasSubsurfaceMaterials && !bSimpleDynamicLighting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 GetSubsurfaceRequiredViewMask(const TArray<FViewInfo>& Views)
|
|
|
|
|
{
|
|
|
|
|
const uint32 ViewCount = Views.Num();
|
|
|
|
|
uint32 ViewMask = 0;
|
|
|
|
|
|
|
|
|
|
// Traverse the views to make sure we only process subsurface if requested by any view.
|
|
|
|
|
for (uint32 ViewIndex = 0; ViewIndex < ViewCount; ++ViewIndex)
|
|
|
|
|
{
|
|
|
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
|
|
|
|
|
|
|
|
if (IsSubsurfaceRequiredForView(View))
|
|
|
|
|
{
|
|
|
|
|
const uint32 ViewBit = 1 << ViewIndex;
|
|
|
|
|
|
|
|
|
|
ViewMask |= ViewBit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ViewMask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsSubsurfaceCheckerboardFormat(EPixelFormat SceneColorFormat)
|
|
|
|
|
{
|
|
|
|
|
int CVarValue = CVarSSSCheckerboard.GetValueOnRenderThread();
|
|
|
|
|
if (CVarValue == 0)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (CVarValue == 1)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (CVarValue == 2)
|
|
|
|
|
{
|
|
|
|
|
switch (SceneColorFormat)
|
|
|
|
|
{
|
|
|
|
|
case PF_A32B32G32R32F:
|
|
|
|
|
case PF_FloatRGBA:
|
|
|
|
|
return false;
|
|
|
|
|
default:
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
// Returns the SS profile texture with a black fallback texture if none exists yet.
|
|
|
|
|
FTextureRHIRef GetSubsurfaceProfileTexture(FRHICommandListImmediate& RHICmdList)
|
|
|
|
|
{
|
|
|
|
|
const IPooledRenderTarget* ProfileTextureTarget = GetSubsufaceProfileTexture_RT(RHICmdList);
|
|
|
|
|
|
|
|
|
|
if (!ProfileTextureTarget)
|
|
|
|
|
{
|
|
|
|
|
// No subsurface profile was used yet
|
|
|
|
|
ProfileTextureTarget = GSystemTextures.BlackDummy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ProfileTextureTarget->GetRenderTargetItem().ShaderResourceTexture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set of common shader parameters shared by all subsurface shaders.
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FSubsurfaceParameters, )
|
2019-04-23 13:26:51 -04:00
|
|
|
SHADER_PARAMETER(FVector4, SubsurfaceParams)
|
|
|
|
|
SHADER_PARAMETER_STRUCT_REF(FSceneTexturesUniformParameters, SceneUniformBuffer)
|
|
|
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
|
|
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, BilinearTextureSampler)
|
2019-04-01 19:37:48 -04:00
|
|
|
SHADER_PARAMETER_TEXTURE(Texture2D, SSProfilesTexture)
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FSubsurfaceParameters GetSubsurfaceCommonParameters(FRHICommandListImmediate& RHICmdList, const FViewInfo& View)
|
2019-04-01 19:37:48 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
|
|
|
|
|
|
|
|
|
|
const float DistanceToProjectionWindow = View.ViewMatrices.GetProjectionMatrix().M[0][0];
|
2019-04-01 19:37:48 -04:00
|
|
|
const float SSSScaleZ = DistanceToProjectionWindow * GetSubsurfaceRadiusScale();
|
|
|
|
|
const float SSSScaleX = SSSScaleZ / SUBSURFACE_KERNEL_SIZE * 0.5f;
|
|
|
|
|
|
|
|
|
|
FSubsurfaceParameters Parameters;
|
|
|
|
|
Parameters.SubsurfaceParams = FVector4(SSSScaleX, SSSScaleZ, 0, 0);
|
2019-04-23 13:26:51 -04:00
|
|
|
Parameters.ViewUniformBuffer = View.ViewUniformBuffer;
|
|
|
|
|
Parameters.SceneUniformBuffer = CreateSceneTextureUniformBuffer(
|
|
|
|
|
SceneContext, View.FeatureLevel, ESceneTextureSetupMode::All, EUniformBufferUsage::UniformBuffer_SingleFrame);
|
|
|
|
|
Parameters.BilinearTextureSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
|
2019-04-01 19:37:48 -04:00
|
|
|
Parameters.SSProfilesTexture = GetSubsurfaceProfileTexture(RHICmdList);
|
|
|
|
|
return Parameters;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
// A shader parameter struct for a single subsurface input texture.
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FSubsurfaceInput, )
|
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FScreenPassTextureViewportParameters, Viewport)
|
|
|
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, Texture)
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FSubsurfaceInput GetSubsurfaceInput(FRDGTextureRef Texture, const FScreenPassTextureViewportParameters& ViewportParameters)
|
2019-04-11 19:32:04 -04:00
|
|
|
{
|
|
|
|
|
FSubsurfaceInput Input;
|
2019-04-23 13:26:51 -04:00
|
|
|
Input.Texture = Texture;
|
|
|
|
|
Input.Viewport = ViewportParameters;
|
2019-04-11 19:32:04 -04:00
|
|
|
return Input;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
// Base class for a subsurface shader.
|
|
|
|
|
class FSubsurfaceShader : public FGlobalShader
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
|
|
|
{
|
|
|
|
|
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
|
|
|
{
|
|
|
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
|
|
|
OutEnvironment.SetDefine(TEXT("SUBSURFACE_RADIUS_SCALE"), SUBSURFACE_RADIUS_SCALE);
|
|
|
|
|
OutEnvironment.SetDefine(TEXT("SUBSURFACE_KERNEL_SIZE"), SUBSURFACE_KERNEL_SIZE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FSubsurfaceShader() = default;
|
|
|
|
|
FSubsurfaceShader(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
|
|
|
|
|
: FGlobalShader(Initializer)
|
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Encapsulates the post processing subsurface scattering pixel shader.
|
|
|
|
|
class FSubsurfaceVisualizePS : public FSubsurfaceShader
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FSubsurfaceVisualizePS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FSubsurfaceVisualizePS, FSubsurfaceShader);
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSubsurfaceParameters, Subsurface)
|
2019-04-11 19:32:04 -04:00
|
|
|
SHADER_PARAMETER_STRUCT(FSubsurfaceInput, SubsurfaceInput0)
|
2019-04-01 19:37:48 -04:00
|
|
|
SHADER_PARAMETER_TEXTURE(Texture2D, MiniFontTexture)
|
2019-04-16 17:12:15 -04:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler0)
|
2019-04-01 19:37:48 -04:00
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSubsurfaceVisualizePS, "/Engine/Private/PostProcessSubsurface.usf", "VisualizePS", SF_Pixel);
|
|
|
|
|
|
|
|
|
|
// Encapsulates the post processing subsurface scattering pixel shader.
|
|
|
|
|
class FSubsurfaceSetupPS : public FSubsurfaceShader
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FSubsurfaceSetupPS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FSubsurfaceSetupPS, FSubsurfaceShader)
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSubsurfaceParameters, Subsurface)
|
2019-04-11 19:32:04 -04:00
|
|
|
SHADER_PARAMETER_STRUCT(FSubsurfaceInput, SubsurfaceInput0)
|
2019-04-16 17:12:15 -04:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler0)
|
2019-04-01 19:37:48 -04:00
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
|
|
|
|
class FDimensionHalfRes : SHADER_PERMUTATION_BOOL("SUBSURFACE_HALF_RES");
|
|
|
|
|
class FDimensionCheckerboard : SHADER_PERMUTATION_BOOL("SUBSURFACE_PROFILE_CHECKERBOARD");
|
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<FDimensionHalfRes, FDimensionCheckerboard>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSubsurfaceSetupPS, "/Engine/Private/PostProcessSubsurface.usf", "SetupPS", SF_Pixel);
|
|
|
|
|
|
|
|
|
|
// Shader for the SSS separable blur.
|
|
|
|
|
class FSubsurfacePS : public FSubsurfaceShader
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FSubsurfacePS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FSubsurfacePS, FSubsurfaceShader);
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSubsurfaceParameters, Subsurface)
|
2019-04-11 19:32:04 -04:00
|
|
|
SHADER_PARAMETER_STRUCT(FSubsurfaceInput, SubsurfaceInput0)
|
2019-04-16 17:12:15 -04:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler0)
|
2019-04-01 19:37:48 -04:00
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
|
|
|
|
|
|
// Direction of the 1D separable filter.
|
|
|
|
|
enum class EDirection : uint32
|
|
|
|
|
{
|
|
|
|
|
Horizontal,
|
|
|
|
|
Vertical,
|
|
|
|
|
MAX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Controls the quality (number of samples) of the blur kernel.
|
|
|
|
|
enum class EQuality : uint32
|
|
|
|
|
{
|
|
|
|
|
Low,
|
|
|
|
|
Medium,
|
|
|
|
|
High,
|
|
|
|
|
MAX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class FDimensionDirection : SHADER_PERMUTATION_ENUM_CLASS("SUBSURFACE_DIRECTION", EDirection);
|
|
|
|
|
class FDimensionQuality : SHADER_PERMUTATION_ENUM_CLASS("SUBSURFACE_QUALITY", EQuality);
|
2019-04-11 19:32:04 -04:00
|
|
|
using FPermutationDomain = TShaderPermutationDomain<FDimensionDirection, FDimensionQuality>;
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
// Returns the sampler state based on the requested SSS filter CVar setting.
|
|
|
|
|
static FSamplerStateRHIParamRef GetSamplerState()
|
|
|
|
|
{
|
|
|
|
|
if (CVarSSSFilter.GetValueOnRenderThread())
|
|
|
|
|
{
|
|
|
|
|
return TStaticSamplerState<SF_Bilinear, AM_Border, AM_Border, AM_Border>::GetRHI();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return TStaticSamplerState<SF_Point, AM_Border, AM_Border, AM_Border>::GetRHI();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the SSS quality level requested by the SSS SampleSet CVar setting.
|
|
|
|
|
static EQuality GetQuality()
|
|
|
|
|
{
|
|
|
|
|
return static_cast<FSubsurfacePS::EQuality>(
|
|
|
|
|
FMath::Clamp(
|
|
|
|
|
CVarSSSSampleSet.GetValueOnRenderThread(),
|
|
|
|
|
static_cast<int32>(FSubsurfacePS::EQuality::Low),
|
|
|
|
|
static_cast<int32>(FSubsurfacePS::EQuality::High)));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSubsurfacePS, "/Engine/Private/PostProcessSubsurface.usf", "MainPS", SF_Pixel);
|
|
|
|
|
|
|
|
|
|
// Encapsulates the post processing subsurface recombine pixel shader.
|
|
|
|
|
class FSubsurfaceRecombinePS : public FSubsurfaceShader
|
|
|
|
|
{
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FSubsurfaceRecombinePS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FSubsurfaceRecombinePS, FSubsurfaceShader);
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
|
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSubsurfaceParameters, Subsurface)
|
2019-04-11 19:32:04 -04:00
|
|
|
SHADER_PARAMETER_STRUCT(FSubsurfaceInput, SubsurfaceInput0)
|
|
|
|
|
SHADER_PARAMETER_STRUCT(FSubsurfaceInput, SubsurfaceInput1)
|
2019-04-16 17:12:15 -04:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler0)
|
|
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler1)
|
2019-04-01 19:37:48 -04:00
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT();
|
|
|
|
|
|
|
|
|
|
// Controls the quality of lighting reconstruction.
|
|
|
|
|
enum class EQuality : uint32
|
|
|
|
|
{
|
|
|
|
|
Low,
|
|
|
|
|
High,
|
|
|
|
|
MAX
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class FDimensionMode : SHADER_PERMUTATION_ENUM_CLASS("SUBSURFACE_RECOMBINE_MODE", ESubsurfaceMode);
|
|
|
|
|
class FDimensionQuality : SHADER_PERMUTATION_ENUM_CLASS("SUBSURFACE_RECOMBINE_QUALITY", EQuality);
|
|
|
|
|
class FDimensionCheckerboard : SHADER_PERMUTATION_BOOL("SUBSURFACE_PROFILE_CHECKERBOARD");
|
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<FDimensionMode, FDimensionQuality, FDimensionCheckerboard>;
|
|
|
|
|
|
|
|
|
|
// Returns the Recombine quality level requested by the SSS Quality CVar setting.
|
|
|
|
|
static EQuality GetQuality(const FViewInfo& View)
|
|
|
|
|
{
|
|
|
|
|
const uint32 QualityCVar = CVarSSSQuality.GetValueOnRenderThread();
|
|
|
|
|
|
|
|
|
|
// Quality is forced to high when the CVar is set to 'auto' and TAA is NOT enabled.
|
|
|
|
|
// TAA improves quality through temporal filtering, making it less necessary to use
|
|
|
|
|
// high quality mode.
|
|
|
|
|
const bool bUseHighQuality = (QualityCVar == -1 && View.AntiAliasingMethod != AAM_TemporalAA);
|
|
|
|
|
|
|
|
|
|
if (QualityCVar == 1 || bUseHighQuality)
|
|
|
|
|
{
|
|
|
|
|
return EQuality::High;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return EQuality::Low;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSubsurfaceRecombinePS, "/Engine/Private/PostProcessSubsurface.usf", "SubsurfaceRecombinePS", SF_Pixel);
|
|
|
|
|
|
|
|
|
|
// Encapsulates a simple copy pixel shader.
|
|
|
|
|
class FSubsurfaceViewportCopyPS : public FSubsurfaceShader
|
|
|
|
|
{
|
|
|
|
|
DECLARE_GLOBAL_SHADER(FSubsurfaceViewportCopyPS);
|
|
|
|
|
SHADER_USE_PARAMETER_STRUCT(FSubsurfaceViewportCopyPS, FSubsurfaceShader);
|
|
|
|
|
|
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
2019-04-23 13:26:51 -04:00
|
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SubsurfaceInput0_Texture)
|
2019-04-16 17:12:15 -04:00
|
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SubsurfaceSampler0)
|
2019-04-01 19:37:48 -04:00
|
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
|
|
|
END_SHADER_PARAMETER_STRUCT();
|
|
|
|
|
|
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
|
|
|
{
|
|
|
|
|
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM4);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSubsurfaceViewportCopyPS, "/Engine/Private/PostProcessSubsurface.usf", "SubsurfaceViewportCopyPS", SF_Pixel);
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
void ComputeSubsurfaceForView(
|
2019-04-01 19:37:48 -04:00
|
|
|
FRDGBuilder& GraphBuilder,
|
2019-04-23 13:26:51 -04:00
|
|
|
const FScreenPassViewInfo& ScreenPassView,
|
|
|
|
|
const FScreenPassTextureViewport& SceneViewport,
|
|
|
|
|
FRDGTextureRef SceneTexture,
|
|
|
|
|
FRDGTextureRef SceneTextureOutput,
|
|
|
|
|
ERenderTargetLoadAction SceneTextureLoadAction)
|
2014-10-15 16:18:43 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
check(SceneTexture);
|
|
|
|
|
check(SceneTextureOutput);
|
|
|
|
|
check(SceneViewport.Extent == SceneTexture->Desc.Extent);
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
const FViewInfo& View = ScreenPassView.View;
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
const FSceneViewFamily* ViewFamily = View.Family;
|
|
|
|
|
|
|
|
|
|
const FRDGTextureDesc& SceneTextureDesc = SceneTexture->Desc;
|
|
|
|
|
|
|
|
|
|
const ESubsurfaceMode SubsurfaceMode = GetSubsurfaceModeForView(View);
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
const bool bHalfRes = (SubsurfaceMode == ESubsurfaceMode::HalfRes);
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
const bool bCheckerboard = IsSubsurfaceCheckerboardFormat(SceneTextureDesc.Format);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
const uint32 ScaleFactor = bHalfRes ? 2 : 1;
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
/**
|
2019-04-23 13:26:51 -04:00
|
|
|
* All subsurface passes within the screen-space subsurface effect can operate at half or full resolution,
|
|
|
|
|
* depending on the subsurface mode. The values are precomputed and shared among all Subsurface textures.
|
2019-04-11 19:32:04 -04:00
|
|
|
*/
|
2019-04-23 13:26:51 -04:00
|
|
|
const FScreenPassTextureViewport SubsurfaceViewport = FScreenPassTextureViewport::CreateDownscaled(SceneViewport, ScaleFactor);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureDesc SubsurfaceTextureDescriptor = SceneTexture->Desc;
|
|
|
|
|
SubsurfaceTextureDescriptor.Extent = SubsurfaceViewport.Extent;
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
const FSubsurfaceParameters SubsurfaceCommonParameters = GetSubsurfaceCommonParameters(GraphBuilder.RHICmdList, View);
|
|
|
|
|
const FScreenPassTextureViewportParameters SubsurfaceViewportParameters = GetScreenPassTextureViewportParameters(SubsurfaceViewport);
|
|
|
|
|
const FScreenPassTextureViewportParameters SceneViewportParameters = GetScreenPassTextureViewportParameters(SceneViewport);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef SetupTexture = SceneTexture;
|
|
|
|
|
FRDGTextureRef SubsurfaceTextureX = nullptr;
|
|
|
|
|
FRDGTextureRef SubsurfaceTextureY = nullptr;
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
FSamplerStateRHIParamRef PointClampSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
2019-04-11 19:32:04 -04:00
|
|
|
FSamplerStateRHIParamRef BilinearBorderSampler = TStaticSamplerState<SF_Bilinear, AM_Border, AM_Border, AM_Border>::GetRHI();
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
/**
|
|
|
|
|
* When in bypass mode, the setup and convolution passes are skipped, but lighting
|
|
|
|
|
* reconstruction is still performed in the recombine pass.
|
|
|
|
|
*/
|
2019-04-01 19:37:48 -04:00
|
|
|
if (SubsurfaceMode != ESubsurfaceMode::Bypass)
|
2014-10-15 16:18:43 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
SetupTexture = GraphBuilder.CreateTexture(SubsurfaceTextureDescriptor, TEXT("SubsurfaceSetupTexture"));
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
// Setup pass outputs the diffuse scene color and depth in preparation for the scatter passes.
|
2014-10-15 16:18:43 -04:00
|
|
|
{
|
2019-04-01 19:37:48 -04:00
|
|
|
FSubsurfaceSetupPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSubsurfaceSetupPS::FParameters>();
|
|
|
|
|
PassParameters->Subsurface = SubsurfaceCommonParameters;
|
2019-04-23 13:26:51 -04:00
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(SetupTexture, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::EStore);
|
|
|
|
|
PassParameters->SubsurfaceInput0 = GetSubsurfaceInput(SceneTexture, SceneViewportParameters);
|
2019-04-16 17:12:15 -04:00
|
|
|
PassParameters->SubsurfaceSampler0 = PointClampSampler;
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
FSubsurfaceSetupPS::FPermutationDomain PixelShaderPermutationVector;
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfaceSetupPS::FDimensionHalfRes>(bHalfRes);
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfaceSetupPS::FDimensionCheckerboard>(bCheckerboard);
|
2019-04-23 13:26:51 -04:00
|
|
|
TShaderMapRef<FSubsurfaceSetupPS> PixelShader(View.ShaderMap, PixelShaderPermutationVector);
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
/**
|
|
|
|
|
* The subsurface viewport is intentionally used as both the target and texture viewport, even though the texture
|
|
|
|
|
* is potentially double the size. This is to ensure that the source UVs map 1-to-1 with pixel centers of the target,
|
|
|
|
|
* in order to ensure that the checkerboard pattern selects the correct pixels from the scene texture. This still works
|
|
|
|
|
* because the texture viewport is normalized into UV space, so it doesn't matter that the dimensions are twice as large.
|
|
|
|
|
*/
|
|
|
|
|
AddDrawScreenPass(GraphBuilder, RDG_EVENT_NAME("SubsurfaceSetup"), ScreenPassView, SubsurfaceViewport, SubsurfaceViewport, *PixelShader, PassParameters);
|
2014-10-15 16:18:43 -04:00
|
|
|
}
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
SubsurfaceTextureX = GraphBuilder.CreateTexture(SubsurfaceTextureDescriptor, TEXT("SubsurfaceTextureX"));
|
|
|
|
|
SubsurfaceTextureY = GraphBuilder.CreateTexture(SubsurfaceTextureDescriptor, TEXT("SubsurfaceTextureY"));
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
FSamplerStateRHIParamRef SubsurfaceSamplerState = FSubsurfacePS::GetSamplerState();
|
|
|
|
|
const FSubsurfacePS::EQuality SubsurfaceQuality = FSubsurfacePS::GetQuality();
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
struct FSubsurfacePassInfo
|
2019-04-01 19:37:48 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
FSubsurfacePassInfo(const TCHAR* InName, FRDGTextureRef InInput, FRDGTextureRef InOutput)
|
2019-04-11 19:32:04 -04:00
|
|
|
: Name(InName)
|
|
|
|
|
, Input(InInput)
|
|
|
|
|
, Output(InOutput)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
const TCHAR* Name;
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef Input;
|
|
|
|
|
FRDGTextureRef Output;
|
2019-04-01 19:37:48 -04:00
|
|
|
};
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
const FSubsurfacePassInfo SubsurfacePassInfoByDirection[] =
|
2019-04-01 19:37:48 -04:00
|
|
|
{
|
2019-04-11 19:32:04 -04:00
|
|
|
{ TEXT("SubsurfaceX"), SetupTexture, SubsurfaceTextureX },
|
|
|
|
|
{ TEXT("SubsurfaceY"), SubsurfaceTextureX, SubsurfaceTextureY },
|
2019-04-01 19:37:48 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Horizontal / Vertical scattering passes using a separable filter.
|
|
|
|
|
for (uint32 DirectionIndex = 0; DirectionIndex < static_cast<uint32>(FSubsurfacePS::EDirection::MAX); ++DirectionIndex)
|
|
|
|
|
{
|
|
|
|
|
const auto Direction = static_cast<FSubsurfacePS::EDirection>(DirectionIndex);
|
|
|
|
|
|
2019-04-11 19:32:04 -04:00
|
|
|
const FSubsurfacePassInfo& PassInfo = SubsurfacePassInfoByDirection[DirectionIndex];
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef TextureInput = PassInfo.Input;
|
|
|
|
|
FRDGTextureRef TextureOutput = PassInfo.Output;
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
FSubsurfacePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSubsurfacePS::FParameters>();
|
|
|
|
|
PassParameters->Subsurface = SubsurfaceCommonParameters;
|
2019-04-23 13:26:51 -04:00
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(TextureOutput, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::EStore);
|
|
|
|
|
PassParameters->SubsurfaceInput0 = GetSubsurfaceInput(TextureInput, SubsurfaceViewportParameters);
|
2019-04-16 17:12:15 -04:00
|
|
|
PassParameters->SubsurfaceSampler0 = SubsurfaceSamplerState;
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
FSubsurfacePS::FPermutationDomain PixelShaderPermutationVector;
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfacePS::FDimensionDirection>(Direction);
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfacePS::FDimensionQuality>(SubsurfaceQuality);
|
2019-04-23 13:26:51 -04:00
|
|
|
TShaderMapRef<FSubsurfacePS> PixelShader(View.ShaderMap, PixelShaderPermutationVector);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
AddDrawScreenPass(GraphBuilder, FRDGEventName(PassInfo.Name), ScreenPassView, SubsurfaceViewport, SubsurfaceViewport, *PixelShader, PassParameters);
|
2019-04-01 19:37:48 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Recombines scattering result with scene color.
|
|
|
|
|
{
|
|
|
|
|
FSubsurfaceRecombinePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSubsurfaceRecombinePS::FParameters>();
|
|
|
|
|
PassParameters->Subsurface = SubsurfaceCommonParameters;
|
2019-04-23 13:26:51 -04:00
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextureOutput, SceneTextureLoadAction, ERenderTargetStoreAction::EStore);
|
|
|
|
|
PassParameters->SubsurfaceInput0 = GetSubsurfaceInput(SceneTexture, SceneViewportParameters);
|
2019-04-16 17:12:15 -04:00
|
|
|
PassParameters->SubsurfaceSampler0 = BilinearBorderSampler;
|
2014-10-15 16:18:43 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
// Scattering output target is only used when scattering is enabled.
|
|
|
|
|
if (SubsurfaceMode != ESubsurfaceMode::Bypass)
|
|
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
PassParameters->SubsurfaceInput1 = GetSubsurfaceInput(SubsurfaceTextureY, SubsurfaceViewportParameters);
|
2019-04-16 17:12:15 -04:00
|
|
|
PassParameters->SubsurfaceSampler1 = BilinearBorderSampler;
|
2014-10-15 16:18:43 -04:00
|
|
|
}
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
const FSubsurfaceRecombinePS::EQuality RecombineQuality = FSubsurfaceRecombinePS::GetQuality(View);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
FSubsurfaceRecombinePS::FPermutationDomain PixelShaderPermutationVector;
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfaceRecombinePS::FDimensionMode>(SubsurfaceMode);
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfaceRecombinePS::FDimensionQuality>(RecombineQuality);
|
|
|
|
|
PixelShaderPermutationVector.Set<FSubsurfaceRecombinePS::FDimensionCheckerboard>(bCheckerboard);
|
2019-04-23 13:26:51 -04:00
|
|
|
TShaderMapRef<FSubsurfaceRecombinePS> PixelShader(View.ShaderMap, PixelShaderPermutationVector);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
/**
|
|
|
|
|
* See the related comment above in the prepare pass. The scene viewport is used as both the target and
|
|
|
|
|
* texture viewport in order to ensure that the correct pixel is sampled for checkerboard rendering.
|
|
|
|
|
*/
|
|
|
|
|
AddDrawScreenPass(GraphBuilder, RDG_EVENT_NAME("SubsurfaceRecombine"), ScreenPassView, SceneViewport, SceneViewport, *PixelShader, PassParameters);
|
2014-10-15 16:18:43 -04:00
|
|
|
}
|
2014-03-14 14:13:41 -04:00
|
|
|
}
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef ComputeSubsurface(
|
2019-04-01 19:37:48 -04:00
|
|
|
FRDGBuilder& GraphBuilder,
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef SceneTexture,
|
|
|
|
|
const TArray<FViewInfo>& Views)
|
2019-04-01 19:37:48 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
const uint32 ViewCount = Views.Num();
|
|
|
|
|
const uint32 ViewMaskAll = (1 << ViewCount) - 1;
|
|
|
|
|
const uint32 ViewMask = GetSubsurfaceRequiredViewMask(Views);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
// Return the original target if no views have subsurface applied.
|
|
|
|
|
if (!ViewMask)
|
|
|
|
|
{
|
|
|
|
|
return SceneTexture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FRDGTextureRef SceneTextureOutput = GraphBuilder.CreateTexture(SceneTexture->Desc, TEXT("SceneColorSubsurface"));
|
|
|
|
|
|
|
|
|
|
ERenderTargetLoadAction SceneTextureLoadAction = ERenderTargetLoadAction::ENoAction;
|
|
|
|
|
|
|
|
|
|
const bool bHasNonSubsurfaceView = ViewMask != ViewMaskAll;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Since we are outputting to a new texture and certain views may not utilize subsurface scattering,
|
|
|
|
|
* we need to copy all non-subsurface views onto the destination texture.
|
|
|
|
|
*/
|
|
|
|
|
if (bHasNonSubsurfaceView)
|
|
|
|
|
{
|
|
|
|
|
FSubsurfaceViewportCopyPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSubsurfaceViewportCopyPS::FParameters>();
|
|
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextureOutput, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::EStore);
|
|
|
|
|
PassParameters->SubsurfaceInput0_Texture = SceneTexture;
|
|
|
|
|
PassParameters->SubsurfaceSampler0 = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
|
|
|
|
|
|
|
|
|
TShaderMapRef<FSubsurfaceViewportCopyPS> PixelShader(Views[0].ShaderMap);
|
|
|
|
|
|
|
|
|
|
const FIntPoint InputTextureSize = SceneTexture->Desc.Extent;
|
|
|
|
|
|
|
|
|
|
GraphBuilder.AddPass(
|
|
|
|
|
RDG_EVENT_NAME("SubsurfaceViewportCopy"),
|
|
|
|
|
PassParameters,
|
|
|
|
|
ERenderGraphPassFlags::None,
|
|
|
|
|
[&Views, ViewMask, ViewCount, PixelShader, InputTextureSize, PassParameters](FRHICommandListImmediate& RHICmdList)
|
|
|
|
|
{
|
|
|
|
|
for (uint32 ViewIndex = 0; ViewIndex < ViewCount; ++ViewIndex)
|
|
|
|
|
{
|
|
|
|
|
const uint32 ViewBit = 1 << ViewIndex;
|
|
|
|
|
|
|
|
|
|
const bool bIsNonSubsurfaceView = (ViewMask & ViewBit) == 0;
|
|
|
|
|
|
|
|
|
|
if (bIsNonSubsurfaceView)
|
|
|
|
|
{
|
|
|
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
|
|
|
const FScreenPassViewInfo ScreenPassView(View);
|
|
|
|
|
|
|
|
|
|
DrawScreenPass(RHICmdList, ScreenPassView, View.ViewRect, View.ViewRect, InputTextureSize, *PixelShader, *PassParameters);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Subsequent render passes should load the texture contents.
|
|
|
|
|
SceneTextureLoadAction = ERenderTargetLoadAction::ELoad;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint32 ViewIndex = 0; ViewIndex < ViewCount; ++ViewIndex)
|
|
|
|
|
{
|
|
|
|
|
const uint32 ViewBit = 1 << ViewIndex;
|
|
|
|
|
|
|
|
|
|
const bool bIsSubsurfaceView = (ViewMask & ViewBit) != 0;
|
|
|
|
|
|
|
|
|
|
if (bIsSubsurfaceView)
|
|
|
|
|
{
|
|
|
|
|
RDG_EVENT_SCOPE(GraphBuilder, "SubsurfaceScattering(ViewId=%d)", ViewIndex);
|
|
|
|
|
|
|
|
|
|
const FViewInfo& View = Views[ViewIndex];
|
|
|
|
|
const FScreenPassViewInfo ScreenPassView(View);
|
|
|
|
|
const FScreenPassTextureViewport SceneViewport(View.ViewRect, SceneTexture);
|
|
|
|
|
|
|
|
|
|
ComputeSubsurfaceForView(GraphBuilder, ScreenPassView, SceneViewport, SceneTexture, SceneTextureOutput, SceneTextureLoadAction);
|
|
|
|
|
|
|
|
|
|
// Subsequent render passes should load the texture contents.
|
|
|
|
|
SceneTextureLoadAction = ERenderTargetLoadAction::ELoad;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SceneTextureOutput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VisualizeSubsurface(
|
|
|
|
|
FRDGBuilder& GraphBuilder,
|
|
|
|
|
const FScreenPassViewInfo& ScreenPassView,
|
|
|
|
|
const FScreenPassTextureViewport& SceneViewport,
|
|
|
|
|
FRDGTextureRef SceneTexture,
|
|
|
|
|
FRDGTextureRef SceneTextureOutput)
|
|
|
|
|
{
|
|
|
|
|
check(SceneTexture);
|
|
|
|
|
check(SceneTextureOutput);
|
|
|
|
|
check(SceneViewport.Extent == SceneTexture->Desc.Extent);
|
|
|
|
|
|
|
|
|
|
const FViewInfo& View = ScreenPassView.View;
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
FSubsurfaceVisualizePS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSubsurfaceVisualizePS::FParameters>();
|
2019-04-23 13:26:51 -04:00
|
|
|
PassParameters->Subsurface = GetSubsurfaceCommonParameters(GraphBuilder.RHICmdList, View);
|
|
|
|
|
PassParameters->RenderTargets[0] = FRenderTargetBinding(SceneTextureOutput, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::EStore);
|
|
|
|
|
PassParameters->SubsurfaceInput0.Texture = SceneTexture;
|
|
|
|
|
PassParameters->SubsurfaceInput0.Viewport = GetScreenPassTextureViewportParameters(SceneViewport);
|
2019-04-16 17:12:15 -04:00
|
|
|
PassParameters->SubsurfaceSampler0 = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
2019-04-01 19:37:48 -04:00
|
|
|
PassParameters->MiniFontTexture = GetMiniFontTexture();
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
TShaderMapRef<FSubsurfaceVisualizePS> PixelShader(View.ShaderMap);
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
GraphBuilder.AddPass(
|
|
|
|
|
RDG_EVENT_NAME("SubsurfaceVisualize"),
|
|
|
|
|
PassParameters,
|
|
|
|
|
ERenderGraphPassFlags::None,
|
2019-04-23 13:26:51 -04:00
|
|
|
[ScreenPassView, SceneViewport, SceneTextureOutput, PixelShader, PassParameters](FRHICommandListImmediate& RHICmdList)
|
2019-04-01 19:37:48 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
DrawScreenPass(RHICmdList, ScreenPassView, SceneViewport, SceneViewport, *PixelShader, *PassParameters);
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
// Draw debug text
|
|
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
const FViewInfo& View = ScreenPassView.View;
|
|
|
|
|
const FSceneViewFamily& ViewFamily = *View.Family;
|
|
|
|
|
FRenderTargetTemp TempRenderTarget(static_cast<FTexture2DRHIParamRef>(SceneTextureOutput->GetRHITexture()), SceneTextureOutput->Desc.Extent);
|
|
|
|
|
FCanvas Canvas(&TempRenderTarget, nullptr, ViewFamily.CurrentRealTime, ViewFamily.CurrentWorldTime, ViewFamily.DeltaWorldTime, View.GetFeatureLevel());
|
2019-04-01 19:37:48 -04:00
|
|
|
|
|
|
|
|
float X = 30;
|
|
|
|
|
float Y = 28;
|
|
|
|
|
const float YStep = 14;
|
|
|
|
|
|
|
|
|
|
FString Line = FString::Printf(TEXT("Visualize Screen Space Subsurface Scattering"));
|
|
|
|
|
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
|
|
|
|
|
|
|
|
Y += YStep;
|
|
|
|
|
|
|
|
|
|
uint32 Index = 0;
|
|
|
|
|
while (GSubsurfaceProfileTextureObject.GetEntryString(Index++, Line))
|
|
|
|
|
{
|
|
|
|
|
Canvas.DrawShadowedString(X, Y += YStep, *Line, GetStatsFont(), FLinearColor(1, 1, 1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bFlush = false;
|
|
|
|
|
const bool bInsideRenderPass = true;
|
|
|
|
|
Canvas.Flush_RenderThread(RHICmdList, bFlush, bInsideRenderPass);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//! Shim methods to hook into the legacy pipeline until the full RDG conversion is complete.
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
void ComputeSubsurfaceShim(FRHICommandListImmediate& RHICmdList, const TArray<FViewInfo>& Views)
|
2014-03-14 14:13:41 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
FSceneRenderTargets& SceneRenderTargets = FSceneRenderTargets::Get(RHICmdList);
|
2019-04-11 19:32:04 -04:00
|
|
|
|
2019-04-01 19:37:48 -04:00
|
|
|
FRDGBuilder GraphBuilder(RHICmdList);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef SceneTexture = GraphBuilder.RegisterExternalTexture(SceneRenderTargets.GetSceneColor(), TEXT("SceneColor"));
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef SceneTextureOutput = ComputeSubsurface(GraphBuilder, SceneTexture, Views);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
// Extract the result texture out and re-assign it to the scene render targets blackboard.
|
|
|
|
|
TRefCountPtr<IPooledRenderTarget> SceneTarget;
|
|
|
|
|
GraphBuilder.QueueTextureExtraction(SceneTextureOutput, &SceneTarget, false);
|
2019-04-01 19:37:48 -04:00
|
|
|
GraphBuilder.Execute();
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
SceneRenderTargets.SetSceneColor(SceneTarget);
|
2014-03-14 14:13:41 -04:00
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
// The RT should be released as early as possible to allow sharing of that memory for other purposes.
|
|
|
|
|
// This becomes even more important with some limited VRam (XBoxOne).
|
|
|
|
|
SceneRenderTargets.SetLightAttenuation(nullptr);
|
2014-10-15 16:18:43 -04:00
|
|
|
}
|
|
|
|
|
|
2019-04-23 13:26:51 -04:00
|
|
|
FRenderingCompositeOutputRef VisualizeSubsurfaceShim(
|
|
|
|
|
FRHICommandListImmediate& RHICmdList,
|
|
|
|
|
FRenderingCompositionGraph& Graph,
|
|
|
|
|
FRenderingCompositeOutputRef Input)
|
2014-10-15 16:18:43 -04:00
|
|
|
{
|
2019-04-23 13:26:51 -04:00
|
|
|
// we need the GBuffer, we release it Process()
|
|
|
|
|
FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, 1);
|
|
|
|
|
|
|
|
|
|
FRenderingCompositePass* SubsurfaceVisualizePass = Graph.RegisterPass(new(FMemStack::Get()) TRCPassForRDG<1, 1>(
|
|
|
|
|
[](FRenderingCompositePass* Pass, FRenderingCompositePassContext& CompositePassContext)
|
|
|
|
|
{
|
|
|
|
|
FRDGBuilder GraphBuilder(CompositePassContext.RHICmdList);
|
|
|
|
|
|
2019-04-23 18:38:43 -04:00
|
|
|
FRDGTextureRef SceneTexture = Pass->CreateRDGTextureForRequiredInput(GraphBuilder, ePId_Input0, TEXT("SceneColor"));
|
2019-04-23 13:26:51 -04:00
|
|
|
FRDGTextureRef SceneTextureOutput = Pass->FindOrCreateRDGTextureForOutput(GraphBuilder, ePId_Output0, SceneTexture->Desc, TEXT("SubsurfaceVisualize"));
|
|
|
|
|
|
|
|
|
|
const FScreenPassViewInfo ScreenPassView(CompositePassContext.View);
|
|
|
|
|
const FScreenPassTextureViewport SceneViewport(CompositePassContext.View.ViewRect, SceneTexture->Desc.Extent);
|
|
|
|
|
VisualizeSubsurface(GraphBuilder, ScreenPassView, SceneViewport, SceneTexture, SceneTextureOutput);
|
|
|
|
|
|
|
|
|
|
Pass->ExtractRDGTextureForOutput(GraphBuilder, ePId_Output0, SceneTextureOutput);
|
|
|
|
|
|
|
|
|
|
GraphBuilder.Execute();
|
|
|
|
|
|
|
|
|
|
FRHICommandListImmediate& RHICmdList = GraphBuilder.RHICmdList;
|
|
|
|
|
FSceneRenderTargets::Get(RHICmdList).AdjustGBufferRefCount(RHICmdList, -1);
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
SubsurfaceVisualizePass->SetInput(ePId_Input0, Input);
|
|
|
|
|
return FRenderingCompositeOutputRef(SubsurfaceVisualizePass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|