Files
UnrealEngineUWP/Engine/Shaders/PostProcessLpvIndirect.usf
Martin Mittring c9355c292c integrated from Orion
optimized shaders to use SvPosition where possible, following change could remove some unused interpolator

[CL 2697164 by Martin Mittring in Main branch]
2015-09-18 12:10:27 -04:00

187 lines
5.7 KiB
Plaintext

//-----------------------------------------------------------------------------
// File: PostProcessLpvIndirect.usf
//
// Summary: Light propagation volume postprocessing
//
// Created: 11/03/2013
//
// Author: mailto:benwood@microsoft.com
//
// Copyright (C) Microsoft. All rights reserved.
//-----------------------------------------------------------------------------
#define ENABLE_LPV_SPECULAR 1
// Directional occlusion
#define DEBUG_USE_RAW_AO 0
#define LPV_OCCLUSION_EDGE_FADE 0
#define ENABLE_DIRECTIONAL_OCCLUSION 1
#define LuminanceVec float3(0.299f,0.587f,0.114f)
#include "Common.usf"
#include "PostProcessCommon.usf"
#include "DeferredLightingCommon.usf"
#include "Random.usf"
#include "LPVFinalPass.usf"
float3 LpvSpecularHighQuality( float3 WorldPosition, float3 R, float Roughness )
{
float Smooth = 1.0f-Roughness;
float offset = Smooth * Smooth * Smooth * Smooth * 8.0f;
// Decreased roughness results in longer ray offsets and higher frequency reflections
float3 specularOut = LPVSpecular( WorldPosition, R, offset );
// To prevent artifacts from very long ray lookups, we do multiple lookups and combine
// with a weighting favouring brighter/further samples
[branch]
if ( offset > 5.0f ) // TODO: Use AO to block rays
{
float3 spec1 = LPVSpecular( WorldPosition, R, offset * 0.5 );
float l1 = dot( spec1, LuminanceVec ) * 0.25;
float l2 = dot( specularOut, LuminanceVec ) * 0.75;
float weight = l2/((l1+l2)+0.0001f);
specularOut = lerp( spec1, specularOut, weight );
}
[branch]
if ( offset > 1.0f )
{
float3 spec1 = ( LPVDiffuse( WorldPosition, R ) / LpvRead.DiffuseIntensity ) * LpvRead.SpecularIntensity; // FIX A BUG. This is horrible!
float l1 = dot( spec1, LuminanceVec ) * 0.25;
float l2 = dot( specularOut, LuminanceVec ) * 0.75;
float weight = l2/((l1+l2)+0.0001f);
specularOut = lerp( spec1, specularOut, weight );
}
return specularOut;
}
void MainPS(in noperspective float4 UVAndScreenPos : TEXCOORD0, float4 SVPos: SV_POSITION, out float4 OutColor : SV_Target0
#if APPLY_SEPARATE_SPECULAR_RT
,out float4 OutSpecular : SV_Target1
#endif
)
{
float2 UV = UVAndScreenPos.xy;
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
FGBufferData GBuffer = ScreenSpaceData.GBuffer;
OutColor = 0;
#if APPLY_SEPARATE_SPECULAR_RT
OutSpecular = 0;
#endif
BRANCH if (GBuffer.ShadingModelID == SHADINGMODELID_UNLIT )
{
return;
}
// screen position in [-1, 1] screen space
float2 ScreenSpacePos = UVAndScreenPos.zw;
float3 ScreenVectorU = mul(float4(ScreenSpacePos, 1, 0), View.ScreenToWorld).xyz;
float3 ScreenVector = normalize(ScreenVectorU);
float SceneDepth = CalcSceneDepth(UV);
float3 WorldPosition = ScreenVectorU * SceneDepth + View.WorldCameraOrigin;
float3 grid = WorldToGrid( WorldPosition );
#if 0 // Potential optimisation - might give worse results if we're outside the grid though
float maxgrid = max(grid.x, max(grid.y, grid.z) );
float mingrid = min(grid.x, min(grid.y, grid.z) );
if ( maxgrid <32 && mingrid > 0)
#endif
{
float3 R = reflect( ScreenVector, GBuffer.WorldNormal );
float3 DiffuseColor = GBuffer.DiffuseColor;
float3 DiffuseNormal = GBuffer.WorldNormal;
float3 SubsurfaceColor = ExtractSubsurfaceColor(ScreenSpaceData.GBuffer);
float3 Diffuse = LPVDiffuse( WorldPosition, DiffuseNormal ) * DiffuseColor;
#if TRANSMISSIVE_LIGHTING_MODEL_LPV
BRANCH if( GBuffer.ShadingModelID != SHADINGMODELID_TRANSMISSIVE )
{
Diffuse += 0.00001f;
}
else
{
float3 SubsurfaceLighting = 0;
float3 BackScatter = ( LPVDiffuse( WorldPosition, -GBuffer.WorldNormal ) ) * GBuffer.Opacity;
SubsurfaceLighting += BackScatter * SubsurfaceColor;
Diffuse += SubsurfaceLighting * 1.0f ;
}
#endif
float3 LpvSpecular = 0;
[branch]
if ( dot( GBuffer.SpecularColor.xyz, GBuffer.SpecularColor.xyz ) >= 0.00001f )
{
LpvSpecular = LpvSpecularHighQuality( WorldPosition, R, GBuffer.Roughness );
}
// apply darkening from ambient occlusion (does not use PostprocessInput1 to set white texture if SSAO is off)
float AmbientOcclusion = GBuffer.GBufferAO * ScreenSpaceData.AmbientOcclusion;
OutColor = float4( Diffuse.xyz, 1 ) * AmbientOcclusion;
#if !ENABLE_LPV_SPECULAR
LpvSpecular = 0;
#endif
#if APPLY_SEPARATE_SPECULAR_RT
// Ambient occlusion already applied with Reflection Environment
// Note: we don't need to apply the BRDF, since it gets applied during reflection apply
// Alpha = 1.0f;
OutSpecular = float4( LpvSpecular, 1 );
#else // APPLY_SEPARATE_SPECULAR_RT
// Combine Specular (same behaviour as PostProcessAmbient)
OutColor.rgb += LpvSpecular;
#endif // APPLY_SEPARATE_SPECULAR_RT
}
}
void DirectionalOcclusionPS(in noperspective float4 UVAndScreenPos : TEXCOORD0, float4 SVPos: SV_POSITION, out float4 OutColor : SV_Target0 )
{
OutColor = float4(1,1,1,1);
#if ENABLE_DIRECTIONAL_OCCLUSION
float2 UV = UVAndScreenPos.xy;
FScreenSpaceData ScreenSpaceData = GetScreenSpaceData(UV);
FGBufferData GBuffer = ScreenSpaceData.GBuffer;
BRANCH if (GBuffer.ShadingModelID != SHADINGMODELID_UNLIT )
{
float2 ScreenSpacePos = UVAndScreenPos.zw;
float3 ScreenVectorU = mul(float4(ScreenSpacePos, 1, 0), View.ScreenToWorld).xyz;
float3 ScreenVector = normalize(ScreenVectorU);
float SceneDepth = CalcSceneDepth(UV);
float3 WorldPosition = ScreenVectorU * SceneDepth + View.WorldCameraOrigin;
float3 grid = WorldToGrid( WorldPosition );
float3 R = reflect( ScreenVector, GBuffer.WorldNormal );
float3 DiffuseNormal = GBuffer.WorldNormal;
float3 SubsurfaceColor = ExtractSubsurfaceColor( ScreenSpaceData.GBuffer );
OutColor = LPVGetDirectionalOcclusion_DiffuseSpec( WorldPosition, R, GBuffer.Roughness, DiffuseNormal ).xyxy;
}
#endif // ENABLE_DIRECTIONAL_OCCLUSION
}