Files
UnrealEngineUWP/Engine/Shaders/DeferredShadingCommon.usf
Daniel Wright 7da79fd159 DFAO optimizations for PS4
* DF lighting GBuffer dependencies packed into 2 textures (saves .1ms)
* Reverted CULL_OBJECTS_TO_RECORD as performance savings are inconsistent
* Added low quality gap fill pass that just does a bilateral filter (saves .4ms)
* Enabled interpolation depth testing (saves .2ms)
* Disabled the temporal stability filter (saves .2ms)
* Overall empty scene cost on PS4 3.77ms -> 2.83ms

[CL 2501856 by Daniel Wright in Main branch]
2015-04-03 18:56:44 -04:00

725 lines
22 KiB
Plaintext

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
DeferredShadingCommon.usf: Common definitions for deferred shading.
=============================================================================*/
#ifndef __DEFERRED_SHADING_COMMON__
#define __DEFERRED_SHADING_COMMON__
#include "LightAccumulator.usf"
// TODO: for CustomGBufferResolvePS() MSAA_SAMPLE_COUNT is defined by C++ code as 2 or 4
// bot not for any other shaders!
#ifndef MSAA_SAMPLE_COUNT
#define MSAA_SAMPLE_COUNT 2
#endif
float3 RGBToYCoCg( float3 RGB )
{
float Y = dot( RGB, float3( 1, 2, 1 ) ) * 0.25;
float Co = dot( RGB, float3( 2, 0, -2 ) ) * 0.25 + ( 0.5 * 256.0 / 255.0 );
float Cg = dot( RGB, float3( -1, 2, -1 ) ) * 0.25 + ( 0.5 * 256.0 / 255.0 );
float3 YCoCg = float3( Y, Co, Cg );
return YCoCg;
}
float3 YCoCgToRGB( float3 YCoCg )
{
float Y = YCoCg.x;
float Co = YCoCg.y - ( 0.5 * 256.0 / 255.0 );
float Cg = YCoCg.z - ( 0.5 * 256.0 / 255.0 );
float R = Y + Co - Cg;
float G = Y + Cg;
float B = Y - Co - Cg;
float3 RGB = float3( R, G, B );
return RGB;
}
// Octahedron Normal Vectors
// [Cigolle 2014, "A Survey of Efficient Representations for Independent Unit Vectors"]
// Mean Max
// oct 8:8 0.33709 0.94424
// snorm 8:8:8 0.17015 0.38588
// oct 10:10 0.08380 0.23467
// snorm 10:10:10 0.04228 0.09598
// oct 12:12 0.02091 0.05874
float2 UnitVectorToOctahedron( float3 N )
{
N.xy /= dot( 1, abs(N) );
if( N.z <= 0 )
{
N.xy = ( 1 - abs(N.yx) ) * ( N.xy >= 0 ? float2(1,1) : float2(-1,-1) );
}
return N.xy;
}
float3 OctahedronToUnitVector( float2 Oct )
{
float3 N = float3( Oct, 1 - dot( 1, abs(Oct) ) );
if( N.z < 0 )
{
N.xy = ( 1 - abs(N.yx) ) * ( N.xy >= 0 ? float2(1,1) : float2(-1,-1) );
}
return normalize(N);
}
float3 Pack1212To888( float2 x )
{
// Pack 12:12 to 8:8:8
#if 0
uint2 x1212 = (uint2)( x * 4095.0 );
uint2 High = x1212 >> 8;
uint2 Low = x1212 & 255;
uint3 x888 = uint3( Low, High.x | (High.y << 4) );
return x888 / 255.0;
#else
float2 x1212 = floor( x * 4095 );
float2 High = floor( x1212 / 256 ); // x1212 >> 8
float2 Low = x1212 - High * 256; // x1212 & 255
float3 x888 = float3( Low, High.x + High.y * 16 );
return saturate( x888 / 255 );
#endif
}
float2 Pack888To1212( float3 x )
{
// Pack 8:8:8 to 12:12
#if 0
uint3 x888 = (uint3)( x * 255.0 );
uint High = x888.z >> 4;
uint Low = x888.z & 15;
uint2 x1212 = x888.xy | uint2( Low << 8, High << 8 );
return x1212 / 4095.0;
#else
float3 x888 = floor( x * 255 );
float High = floor( x888.z / 16 ); // x888.z >> 4
float Low = x888.z - High * 16; // x888.z & 15
float2 x1212 = x888.xy + float2( Low, High ) * 256;
return saturate( x1212 / 4095 );
#endif
}
float3 EncodeNormal( float3 N )
{
return N * 0.5 + 0.5;
//return Pack1212To888( UnitVectorToOctahedron( N ) * 0.5 + 0.5 );
}
float3 DecodeNormal( float3 N )
{
return N * 2 - 1;
//return OctahedronToUnitVector( Pack888To1212( N ) * 2 - 1 );
}
#if USE_FRAMEBUFFER_SRGB
float3 EncodeBaseColor(float3 BaseColor)
{
// we use sRGB on the render target to give more precision to the darks
return BaseColor;
}
float3 DecodeBaseColor(float3 BaseColor)
{
// we use sRGB on the render target to give more precision to the darks
return BaseColor;
}
#else // @todo: remove once Apple fixes radr://16754329 AMD Cards don't always perform FRAMEBUFFER_SRGB if the draw FBO has mixed sRGB & non-SRGB colour attachments
float3 EncodeBaseColor(float3 BaseColor)
{
// Gamma 2.0
return sqrt( saturate(BaseColor) );
}
float3 DecodeBaseColor(float3 BaseColor)
{
return Square( BaseColor );
}
#endif
float3 EncodeSubsurfaceColor(float3 SubsurfaceColor)
{
return sqrt(saturate(SubsurfaceColor));
}
// @param SubsurfaceProfile 0..1, SubsurfaceProfileId = int(x * 255)
float3 EncodeSubsurfaceProfile(float SubsurfaceProfile)
{
return float3(SubsurfaceProfile, 0, 0);
}
float EncodeIndirectIrradiance(float IndirectIrradiance)
{
float L = IndirectIrradiance;
const float LogBlackPoint = 0.00390625; // exp2(-8);
return log2( L + LogBlackPoint ) / 16 + 0.5;
}
float DecodeIndirectIrradiance(float IndirectIrradiance)
{
// LogL -> L
float LogL = IndirectIrradiance;
const float LogBlackPoint = 0.00390625; // exp2(-8);
return exp2( LogL * 16 - 8 ) - LogBlackPoint; // 1 exp2, 1 smad, 1 ssub
}
float ComputeAngleFromRoughness( float Roughness, const float Threshold = 0.04f )
{
#if 1
float Angle = 3 * Square( Roughness );
#else
const float LogThreshold = log2( Threshold );
float Power = 0.5 / pow( Roughness, 4 ) - 0.5;
float Angle = acos( exp2( LogThreshold / Power ) );
#endif
return Angle;
}
float ComputeRoughnessFromAngle( float Angle, const float Threshold = 0.04f )
{
#if 1
float Roughness = sqrt( 0.33333 * Angle );
#else
const float LogThreshold = log2( Threshold );
float Power = LogThreshold / log2( cos( Angle ) );
float Roughness = sqrt( sqrt( 2 / (Power * 4 + 2) ) );
#endif
return Roughness;
}
float AddAngleToRoughness( float Angle, float Roughness )
{
return saturate( sqrt( Square( Roughness ) + 0.33333 * Angle ) );
}
// @param Scalar clamped in 0..1 range
// @param Mask 0..1
// @return 8bit in range 0..1
float Encode71(float Scalar, uint Mask)
{
return
127.0f / 255.0f * saturate(Scalar) +
128.0f / 255.0f * Mask;
}
// 8bit reinterpretation as 7bit,1bit
// @param Scalar 0..1
// @param Mask 0..1
// @return 7bit in 0.1
float Decode71(float Scalar, out uint Mask)
{
Mask = (uint)(Scalar > 0.5f);
return (Scalar - 0.5f * Mask) * 2.0f;
}
#define SHADINGMODELID_UNLIT 0
#define SHADINGMODELID_DEFAULT_LIT 1
#define SHADINGMODELID_SUBSURFACE 2
#define SHADINGMODELID_PREINTEGRATED_SKIN 3
#define SHADINGMODELID_CLEAR_COAT 4
#define SHADINGMODELID_SUBSURFACE_PROFILE 5
#define SHADINGMODELID_TWOSIDED_FOLIAGE 6
#define SHADINGMODELID_NUM 7
float EncodeShadingModelId(uint ShadingModelId)
{
return (ShadingModelId + .5f) / (float)SHADINGMODELID_NUM;
}
uint DecodeShadingModelId(float InPackedChannel)
{
return (uint)( InPackedChannel * SHADINGMODELID_NUM );
}
bool IsSubsurfaceModel(int ShadingModel)
{
return ShadingModel == SHADINGMODELID_SUBSURFACE
|| ShadingModel == SHADINGMODELID_PREINTEGRATED_SKIN
|| ShadingModel == SHADINGMODELID_SUBSURFACE_PROFILE
|| ShadingModel == SHADINGMODELID_TWOSIDED_FOLIAGE;
}
// all values that are output by the forward rendering pass
struct FGBufferData
{
// normalized
float3 WorldNormal;
// 0..1 (derived from BaseColor, Metalness, Specular)
float3 DiffuseColor;
// 0..1 (derived from BaseColor, Metalness, Specular)
float3 SpecularColor;
// 0..1
float3 BaseColor;
// 0..1
float Metallic;
// 0..1
float Specular;
// 0..1
float3 CustomData;
// Indirect irradiance luma
float IndirectIrradiance;
// Static shadow factors for channels assigned by Lightmass
// Lights using static shadowing will pick up the appropriate channel in their deferred pass
float4 PrecomputedShadowFactors;
// 0..1
float Roughness;
// 0..1
float Opacity;
// 0..1 ambient occlusion e.g.SSAO, wet surface mask, skylight mask, ...
float GBufferAO;
// 0..255
uint ShadingModelID;
// 0..1 decal receiver mask
uint DecalMask;
// 0..1
uint HasDistanceFieldRepresentation;
// 0..1
uint HasHeightfieldRepresentation;
// in world units
float CustomDepth;
// in unreal units (linear), can be used to reconstruct world position,
// only valid when decoding the GBuffer as the value gets reconstructed from the Z buffer
float Depth;
// Velocity for motion blur (only used when WRITES_VELOCITY_TO_GBUFFER is enabled)
float4 Velocity;
};
// all values that are output by the forward rendering pass
struct FDBufferData
{
// 0..1, premultiplied with ColorOpacity
float3 PreMulColor;
// 0:opaque ..1:see through
float ColorOpacity;
// -1..1, premultiplied with NormalOpacity
float3 PreMulWorldNormal;
// 0:opaque ..1:see through
float NormalOpacity;
// 0..1, premultiplied with RoughnessOpacity
float PreMulRoughness;
// 0:opaque ..1:see through
float RoughnessOpacity;
};
struct FScreenSpaceData
{
// GBuffer (material attributes from forward rendering pass)
FGBufferData GBuffer;
// 0..1, only valid in some passes, 1 if off
float AmbientOcclusion;
};
/** Populates OutGBufferA, B and C */
void EncodeGBuffer(
FGBufferData GBuffer,
out float4 OutGBufferA,
out float4 OutGBufferB,
out float4 OutGBufferC,
out float4 OutGBufferD,
out float4 OutGBufferE,
out float4 OutGBufferVelocity,
float QuantizationBias = 0 // -0.5 to 0.5 random float. Used to bias quantization.
)
{
OutGBufferA.rgb = EncodeNormal( GBuffer.WorldNormal );
// compress in 2 bits
// Note: distance field lighting dependencies (normal, representation bits) packed for minimal texture fetches
uint PackedAlpha = GBuffer.HasHeightfieldRepresentation * 2 + (GBuffer.HasDistanceFieldRepresentation);
OutGBufferA.a = PackedAlpha * (1.0 / 3.0);
if (GBuffer.ShadingModelID == SHADINGMODELID_UNLIT)
{
OutGBufferB = 0;
OutGBufferC = 0;
OutGBufferD = 0;
}
else
{
OutGBufferB.r = GBuffer.Metallic;
OutGBufferB.g = GBuffer.Specular;
OutGBufferB.b = GBuffer.Roughness;
OutGBufferC.rgb = EncodeBaseColor(GBuffer.BaseColor);
#if ALLOW_STATIC_LIGHTING
// No space for AO. Multiply IndirectIrradiance by AO instead of storing.
OutGBufferC.a = EncodeIndirectIrradiance(GBuffer.IndirectIrradiance * GBuffer.GBufferAO) + QuantizationBias * (1.0 / 255.0);
#else
OutGBufferC.a = GBuffer.GBufferAO;
#endif
OutGBufferB.a = Encode71(EncodeShadingModelId(GBuffer.ShadingModelID), GBuffer.DecalMask);
OutGBufferD.r = GBuffer.Opacity;
OutGBufferD.gba = GBuffer.CustomData;
}
OutGBufferE = GBuffer.PrecomputedShadowFactors;
#if WRITES_VELOCITY_TO_GBUFFER
OutGBufferVelocity = GBuffer.Velocity;
#else
OutGBufferVelocity = 0;
#endif
}
/** Populates FGBufferData */
FGBufferData DecodeGBufferData(
float4 InGBufferA,
float4 InGBufferB,
float4 InGBufferC,
float4 InGBufferD,
float4 InGBufferE,
float4 InGBufferVelocity,
float CustomNativeDepth,
float SceneDepth,
bool bGetNormalizedNormal)
{
FGBufferData GBuffer;
GBuffer.WorldNormal = DecodeNormal( InGBufferA.xyz );
if(bGetNormalizedNormal)
{
GBuffer.WorldNormal = normalize(GBuffer.WorldNormal);
}
uint PackedAlpha = (uint)( InGBufferA.a * 3.999 );
GBuffer.HasHeightfieldRepresentation = (PackedAlpha & 2) != 0;
GBuffer.HasDistanceFieldRepresentation = PackedAlpha & 1;
GBuffer.DecalMask = 0;
GBuffer.ShadingModelID = DecodeShadingModelId(Decode71(InGBufferB.a, GBuffer.DecalMask));
GBuffer.BaseColor = DecodeBaseColor(InGBufferC.rgb);
GBuffer.Metallic = InGBufferB.r;
GBuffer.Specular = InGBufferB.g;
GBuffer.Opacity = InGBufferD.r;
GBuffer.Roughness = InGBufferB.b;
GBuffer.CustomData = InGBufferD.gba;
#if ALLOW_STATIC_LIGHTING
GBuffer.GBufferAO = 1;
GBuffer.IndirectIrradiance = DecodeIndirectIrradiance(InGBufferC.a);
#else
GBuffer.GBufferAO = InGBufferC.a;
GBuffer.IndirectIrradiance = 1;
#endif
GBuffer.PrecomputedShadowFactors = InGBufferE;
GBuffer.CustomDepth = ConvertFromDeviceZ(CustomNativeDepth);
GBuffer.Depth = SceneDepth;
// derived from BaseColor, Metalness, Specular
{
GBuffer.DiffuseColor = GBuffer.BaseColor - GBuffer.BaseColor * GBuffer.Metallic;
GBuffer.SpecularColor = lerp( 0.08 * GBuffer.Specular.xxx, GBuffer.BaseColor, GBuffer.Metallic );
#if USE_DEVELOPMENT_SHADERS
{
// this feature is only needed for development/editor - we can compile it out for a shipping build (see r.CompileShadersForDevelopment cvar help)
GBuffer.DiffuseColor = GBuffer.DiffuseColor * View.DiffuseOverrideParameter.www + View.DiffuseOverrideParameter.xyz;
GBuffer.SpecularColor = GBuffer.SpecularColor * View.SpecularOverrideParameter.w + View.SpecularOverrideParameter.xyz;
}
#endif //USE_DEVELOPMENT_SHADERS
}
GBuffer.Velocity = InGBufferVelocity;
return GBuffer;
}
/** Populates FDBufferData */
FDBufferData DecodeDBufferData(
float4 DBufferA,
float4 DBufferB,
float2 DBufferC)
{
FDBufferData ret;
// UNORM 4 channel
ret.PreMulColor = DBufferA.rgb;
ret.ColorOpacity = DBufferA.a;
// UNORM 4 channel, 128/255 represents 0
ret.PreMulWorldNormal = DBufferB.rgb * 2 - (256.0 / 255.0);
ret.NormalOpacity = DBufferB.a;
// UNORM 2 channel
ret.PreMulRoughness = DBufferC.r;
ret.RoughnessOpacity = DBufferC.g;
return ret;
}
/** Populates DBufferA, DBufferB, DBufferC as float4 and puts opacity in alpha for frame buffer blending */
// @param MultiOpacity .x: Color, .y:Normal, .z:Roughness
void EncodeDBufferData(FGBufferData GBufferData, float3 MultiOpacity,
out float4 DBufferA,
out float4 DBufferB,
out float4 DBufferC)
{
// UNORM 4 channel
DBufferA = float4(GBufferData.BaseColor, MultiOpacity.x);
// UNORM 4 channel, 128/255 represents 0
DBufferB = float4(GBufferData.WorldNormal * 0.5f + 128.0f/255.0f, MultiOpacity.y);
// UNORM 2 channel
DBufferC = float4(GBufferData.Roughness, 0, 0, MultiOpacity.z);
// no need to output any data if the channel isn't used anyway (for DX10 we don't adjust the FrameBufferBlend state - it doesn't support different blend modes for different MRT)
{
#if !MATERIAL_DBUFFERA
DBufferA = 0;
#endif
#if !MATERIAL_DBUFFERB
DBufferB = 0;
#endif
#if !MATERIAL_DBUFFERC
DBufferC = 0;
#endif
}
}
float3 ExtractSubsurfaceColor(FGBufferData BufferData)
{
return Square(BufferData.CustomData);
}
uint ExtractSubsurfaceProfileInt(FGBufferData BufferData)
{
// can be optimized
return uint(BufferData.CustomData.r * 255.0f + 0.5f);
}
/** Populates DBufferA, DBufferB, DBufferC as float4 and puts opacity in alpha for frame buffer blending */
void ApplyDBufferData(
FDBufferData DBufferData, inout float3 WorldNormal, inout float3 SubsurfaceColor, inout float Roughness,
inout float3 BaseColor, inout float Metallic, inout float Specular )
{
WorldNormal = WorldNormal * DBufferData.NormalOpacity + DBufferData.PreMulWorldNormal;
Roughness = Roughness * DBufferData.RoughnessOpacity + DBufferData.PreMulRoughness;
SubsurfaceColor *= DBufferData.ColorOpacity;
BaseColor = BaseColor * DBufferData.ColorOpacity + DBufferData.PreMulColor;
Metallic = Metallic * DBufferData.ColorOpacity + 0; // decals are always no metallic
Specular = lerp(0.5f, Specular, DBufferData.ColorOpacity); // most non metal materials have a specular of 4% which is 0.5 in this scale
}
Texture2D DBufferATexture;
SamplerState DBufferATextureSampler;
Texture2D DBufferBTexture;
SamplerState DBufferBTextureSampler;
Texture2D DBufferCTexture;
SamplerState DBufferCTextureSampler;
Texture2D ScreenSpaceAOTexture;
SamplerState ScreenSpaceAOTextureSampler;
Texture2D CustomDepthTexture;
SamplerState CustomDepthTextureSampler;
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
// In all but SM5 we need to explicitly declare how many samples are in a multisampled texture.
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
#define FMultisampledGBuffer Texture2DMS<float4>
#else
#define FMultisampledGBuffer Texture2DMS<float4,MSAA_SAMPLE_COUNT>
#endif
Texture2D<float4> DBufferATextureNonMS;
Texture2D<float4> DBufferBTextureNonMS;
Texture2D<float2> DBufferCTextureNonMS;
Texture2D<float4> ScreenSpaceAOTextureNonMS;
Texture2D<float> CustomDepthTextureNonMS;
// @param PixelPos - integer pixel pos (from left top)
FGBufferData GetGBufferDataUint(uint2 PixelPos, bool bGetNormalizedNormal = true)
{
float4 GBufferA = GBuffers.GBufferATextureNonMS.Load(int3(PixelPos, 0));
float4 GBufferB = GBuffers.GBufferBTextureNonMS.Load(int3(PixelPos, 0));
float4 GBufferC = GBuffers.GBufferCTextureNonMS.Load(int3(PixelPos, 0));
float4 GBufferD = GBuffers.GBufferDTextureNonMS.Load(int3(PixelPos, 0));
float CustomNativeDepth = CustomDepthTextureNonMS.Load(int3(PixelPos, 0)).r;
#if ALLOW_STATIC_LIGHTING
float4 GBufferE = GBuffers.GBufferETextureNonMS.Load(int3(PixelPos, 0));
#else
float4 GBufferE = 1;
#endif
#if WRITES_VELOCITY_TO_GBUFFER
float4 GBufferVelocity = GBuffers.GBufferVelocityTextureNonMS.Load(int3(PixelPos, 0));
#else
float4 GBufferVelocity = 0;
#endif
float SceneDepth = CalcSceneDepth(PixelPos);
return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferVelocity, CustomNativeDepth, SceneDepth, bGetNormalizedNormal);
}
FDBufferData GetDBufferData(uint2 PixelPos)
{
float4 DBufferA = DBufferATextureNonMS.Load(int3(PixelPos, 0));
float4 DBufferB = DBufferBTextureNonMS.Load(int3(PixelPos, 0));
float2 DBufferC = DBufferCTextureNonMS.Load(int3(PixelPos, 0)).rg;
return DecodeDBufferData(DBufferA, DBufferB, DBufferC);
}
// @param PixelPos - integer pixel pos (from left top)
FScreenSpaceData GetScreenSpaceDataUint(uint2 PixelPos, bool bGetNormalizedNormal = true)
{
FScreenSpaceData Out;
Out.GBuffer = GetGBufferDataUint(PixelPos, bGetNormalizedNormal);
// todo: optimize
// this is what we want but because WhiteDummy (in case AO is disabled) doesn't support this lookup we do the code below
// Out.AmbientOcclusion = ScreenSpaceAOTextureNonMS.Load(int3(PixelPos, 0)).r;
{
uint width;
uint height;
uint levels;
ScreenSpaceAOTextureNonMS.GetDimensions(0, width, height, levels);
float4 ScreenSpaceAO = Texture2DSampleLevel(ScreenSpaceAOTexture, ScreenSpaceAOTextureSampler, (PixelPos + 0.5f) / float2(width, height), 0);
Out.AmbientOcclusion = ScreenSpaceAO.r;
}
return Out;
}
#endif
// @param UV - UV space in the GBuffer textures (BufferSize resolution)
FGBufferData GetGBufferData(float2 UV, bool bGetNormalizedNormal = true)
{
#if 0 //METAL_MRT_PROFILE
// @todo metal mrt: The deferred renderer isn't keeping these in tiled memory all the time - we don't know when this makes sense
// versus just sampling a bound resolved texture
float4 GBufferA = FramebufferFetchMRT(1);
float4 GBufferB = FramebufferFetchMRT(2);
float4 GBufferC = FramebufferFetchMRT(3);
float4 GBufferD = FramebufferFetchMRT(4);
// @todo metal mrt: We can't framebuffer fetch the depth, can we jam it in somewhere?
float CustomNativeDepth = 0.5;
#if ALLOW_STATIC_LIGHTING
float4 GBufferE = FramebufferFetchMRT(5);
#else
float4 GBufferE = 1;
#endif
#else
float4 GBufferA = Texture2DSampleLevel(GBuffers.GBufferATexture, GBuffers.GBufferATextureSampler, UV, 0);
float4 GBufferB = Texture2DSampleLevel(GBuffers.GBufferBTexture, GBuffers.GBufferBTextureSampler, UV, 0);
float4 GBufferC = Texture2DSampleLevel(GBuffers.GBufferCTexture, GBuffers.GBufferCTextureSampler, UV, 0);
float4 GBufferD = Texture2DSampleLevel(GBuffers.GBufferDTexture, GBuffers.GBufferDTextureSampler, UV, 0);
float CustomNativeDepth = Texture2DSampleLevel(CustomDepthTexture, CustomDepthTextureSampler, UV, 0).r;
#if ALLOW_STATIC_LIGHTING
float4 GBufferE = Texture2DSampleLevel(GBuffers.GBufferETexture, GBuffers.GBufferETextureSampler, UV, 0);
#else
float4 GBufferE = 1;
#endif
#if WRITES_VELOCITY_TO_GBUFFER
float4 GBufferVelocity = Texture2DSampleLevel(GBuffers.GBufferVelocityTexture, GBuffers.GBufferVelocityTextureSampler, UV, 0);
#else
float4 GBufferVelocity = 0;
#endif
#endif
float SceneDepth = CalcSceneDepth(UV);
return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferVelocity, CustomNativeDepth, SceneDepth, bGetNormalizedNormal);
}
// Minimal path for just the lighting model, used to branch around unlit pixels (skybox)
uint GetShadingModelId(float2 UV)
{
bool Unused;
return DecodeShadingModelId(Decode71(Texture2DSampleLevel(GBuffers.GBufferBTexture, GBuffers.GBufferBTextureSampler, UV, 0).a, Unused));
}
// @param UV - UV space in the DBuffer textures (BufferSize resolution)
FDBufferData GetDBufferData(float2 UV)
{
#if SUPPORTS_INDEPENDENT_SAMPLERS
// Share samplers to give artists more
float4 DBufferA = Texture2DSampleLevel(DBufferATexture, DBufferATextureSampler, UV, 0);
float4 DBufferB = Texture2DSampleLevel(DBufferBTexture, DBufferATextureSampler, UV, 0);
float2 DBufferC = Texture2DSampleLevel(DBufferCTexture, DBufferATextureSampler, UV, 0).rg;
#else
float4 DBufferA = Texture2DSampleLevel(DBufferATexture, DBufferATextureSampler, UV, 0);
float4 DBufferB = Texture2DSampleLevel(DBufferBTexture, DBufferBTextureSampler, UV, 0);
float2 DBufferC = Texture2DSampleLevel(DBufferCTexture, DBufferCTextureSampler, UV, 0).rg;
#endif
return DecodeDBufferData(DBufferA, DBufferB, DBufferC);
}
// @param UV - UV space in the GBuffer textures (BufferSize resolution)
FScreenSpaceData GetScreenSpaceData(float2 UV, bool bGetNormalizedNormal = true)
{
FScreenSpaceData Out;
Out.GBuffer = GetGBufferData(UV, bGetNormalizedNormal);
float4 ScreenSpaceAO = Texture2DSampleLevel(ScreenSpaceAOTexture, ScreenSpaceAOTextureSampler, UV, 0);
Out.AmbientOcclusion = ScreenSpaceAO.r;
return Out;
}
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
FGBufferData GetGBufferDataMS(int2 IntUV, uint SampleIndex, bool bGetNormalizedNormal = true)
{
float4 GBufferA = GBuffers.GBufferATextureMS.Load(IntUV, SampleIndex);
float4 GBufferB = GBuffers.GBufferBTextureMS.Load(IntUV, SampleIndex);
float4 GBufferC = GBuffers.GBufferCTextureMS.Load(IntUV, SampleIndex);
float4 GBufferD = GBuffers.GBufferDTextureMS.Load(IntUV, SampleIndex);
float CustomNativeDepth = CustomDepthTextureNonMS.Load(int3(IntUV, 0)).r;
#if ALLOW_STATIC_LIGHTING
float4 GBufferE = GBuffers.GBufferETextureMS.Load(IntUV, SampleIndex);
#else
float4 GBufferE = 1;
#endif
float DeviceZ = SceneDepthSurface.Load(IntUV, SampleIndex);
float SceneDepth = ConvertFromDeviceZ(DeviceZ);
#if WRITES_VELOCITY_TO_GBUFFER
float4 GBufferVelocity = GBuffers.GBufferVelocityTextureMS.Load(IntUV, SampleIndex);
#else
float4 GBufferVelocity = 0;
#endif
return DecodeGBufferData(GBufferA, GBufferB, GBufferC, GBufferD, GBufferE, GBufferVelocity, CustomNativeDepth, SceneDepth, bGetNormalizedNormal);
}
FGBufferData GetGBufferDataMS(float2 UV, uint SampleIndex, bool bGetNormalizedNormal = true)
{
float2 SurfaceDimensions;
float NumSurfaceSamples;
// assuming all GBuffers share the same size
GBuffers.GBufferCTextureMS.GetDimensions(SurfaceDimensions.x, SurfaceDimensions.y, NumSurfaceSamples);
int2 IntUV = (int2)trunc(UV * SurfaceDimensions);
return GetGBufferDataMS(IntUV, SampleIndex, bGetNormalizedNormal);
}
#endif
#endif // __DEFERRED_SHADING_COMMON__