Files
UnrealEngineUWP/Engine/Shaders/PlanarReflectionShared.usf
Ben Marsh 20bf0eb6a1 Updating copyright notices to 2017 (copying from //Tasks/UE4/Dev-Copyright-2017).
#rb none
#lockdown Nick.Penwarden

[CL 3226823 by Ben Marsh in Main branch]
2016-12-08 08:52:44 -05:00

104 lines
5.1 KiB
Plaintext

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
PlanarReflectionShared.usf
=============================================================================*/
// World space reflection plane, normalized
float4 ReflectionPlane;
float3 PlanarReflectionOrigin;
float4 PlanarReflectionXAxis;
float4 PlanarReflectionYAxis;
// Used to transform normals into the mirrored space
float3x4 InverseTransposeMirrorMatrix;
// x = scale for plane distance fading, y = bias for plane distance fading, z = controls normal distortion strength
float3 PlanarReflectionParameters;
// x = scale for angle fading, y = bias for angle fading
float2 PlanarReflectionParameters2;
// Projection matrix that was used to capture PlanarReflectionTexture
float4x4 ProjectionWithExtraFOV[2];
// True if we're rendering a stereo planar reflection
bool bIsStereo;
Texture2D PlanarReflectionTexture;
SamplerState PlanarReflectionSampler;
float4 ComputePlanarReflections(float3 WorldPosition, float3 WorldNormal, float Roughness, SamplerState SharedClampSampler)
{
float4 OutPlanarReflection = 0;
float PlaneDistance = dot(ReflectionPlane, float4(WorldPosition, -1));
float DistanceFade = 1 - saturate(abs(PlaneDistance) * PlanarReflectionParameters.x + PlanarReflectionParameters.y);
float3 PlaneOriginToWorldPosition = WorldPosition - PlanarReflectionOrigin;
float XAxisDistance = dot(PlaneOriginToWorldPosition, PlanarReflectionXAxis.xyz);
float XAxisFade = saturate((PlanarReflectionXAxis.w - abs(XAxisDistance)) * PlanarReflectionParameters.x);
float YAxisDistance = dot(PlaneOriginToWorldPosition, PlanarReflectionYAxis.xyz);
float YAxisFade = saturate((PlanarReflectionYAxis.w - abs(YAxisDistance)) * PlanarReflectionParameters.x);
DistanceFade *= XAxisFade * YAxisFade;
BRANCH
if (DistanceFade > 0)
{
// CameraToPixel in the main view is what we used as ReflectionVector when rendering the reflection pass to PlanarReflectionTexture
float3 CameraToPixel = normalize(WorldPosition - ResolvedView.WorldCameraOrigin);
// Reflect the effective ReflectionVector in mirrored space to get the original camera vector
float3 MirroredCameraVector = reflect(CameraToPixel, -ReflectionPlane.xyz);
// Transform the GBuffer normal into mirrored space
float3 MirroredNormal = mul(WorldNormal, (float3x3)InverseTransposeMirrorMatrix);
// Reflect the original camera vector across the GBuffer normal in mirrored space
float3 MirroredReflectionVectorOffNormal = reflect(MirroredCameraVector, MirroredNormal);
// At this point we have a new reflection vector off of the GBuffer normal, and we need to approximate its intersection with the scene
// An accurate intersection would ray trace the planar reflection depth buffer
// As an approximation we are just intersecting with a user defined sphere
float3 VirtualReflectionSpherePosition = WorldPosition + MirroredReflectionVectorOffNormal * PlanarReflectionParameters.z;
// Transform the intersection position into view space
float3 ViewVirtualReflectionSpherePosition = mul(float4(VirtualReflectionSpherePosition + ResolvedView.PreViewTranslation.xyz, 1), ResolvedView.TranslatedWorldToView).xyz;
// Transform the intersection position into clip space using the same projection matrix used to render PlanarReflectionTexture
float4 ClipVirtualReflectionSpherePosition = mul(float4(ViewVirtualReflectionSpherePosition, 1), ProjectionWithExtraFOV[ResolvedView.StereoPassIndex]);
// Compute viewport UVs from clip space position.
// Note not using View.ScreenPositionScaleBias because PlanarReflectionTexture is exactly sized with the viewport, unlike the scene render targets
float2 ViewportUV = ClipVirtualReflectionSpherePosition.xy / ClipVirtualReflectionSpherePosition.w * float2(.5f, -.5f) + .5f;
// When rendering in stereo, we need to scale, shift and clamp the viewport uvs to match the correct area in screen space for the view
#if !MULTI_VIEW
BRANCH
if (bIsStereo)
{
const float StereoShift[2] = { 0.0f, 1.0f };
const float2 ViewClamp[2] = { float2(0.0f, 0.5f), float2(0.5f, 1.0f) };
ViewportUV.x *= 0.5f * ResolvedView.HMDEyePaddingOffset;
ViewportUV.x += StereoShift[ResolvedView.StereoPassIndex] * (1.0f - 0.5 * ResolvedView.HMDEyePaddingOffset);
ViewportUV.x = clamp(ViewportUV.x, ViewClamp[ResolvedView.StereoPassIndex].x, ViewClamp[ResolvedView.StereoPassIndex].y);
}
#endif
float AngleFade = saturate(dot(ReflectionPlane.xyz, WorldNormal) * PlanarReflectionParameters2.x + PlanarReflectionParameters2.y);
float RoughnessFade = 1 - saturate((Roughness - .2f) * 10.0f);
float FinalFade = DistanceFade * AngleFade * RoughnessFade;
float4 PlanarReflectionTextureValue = Texture2DSampleLevel(
PlanarReflectionTexture,
#if SUPPORTS_INDEPENDENT_SAMPLERS
SharedClampSampler,
#else
PlanarReflectionSampler,
#endif
ViewportUV,
0);
// Fade out in regions of the planar reflection that weren't written to, so we can composite with other reflection methods
FinalFade *= PlanarReflectionTextureValue.a;
OutPlanarReflection.rgb = PlanarReflectionTextureValue.rgb * FinalFade;
OutPlanarReflection.a = FinalFade;
}
return OutPlanarReflection;
}