2019-09-20 10:28:29 -04:00
/*=============================================================================
DistortionCommon.ush
=============================================================================*/
#include "Common.ush"
float2 ComputeBufferUVDistortion(
in FMaterialPixelParameters MaterialParameters, in FPixelMaterialInputs PixelMaterialInputs, in ViewState ResolvedView,
2022-12-02 03:49:35 -05:00
in half3 WorldNormal, in float InMaterialIOR,
in float4 DistortionParameters, in float2 ScreenUV, in FMaterialRefractionData RefractionData, in bool TryToClip, in uint EyeIndex)
2019-09-20 10:28:29 -04:00
{
2021-12-10 05:09:55 -05:00
half3 ViewNormal = normalize(TransformWorldVectorToView(WorldNormal));
2019-09-20 10:28:29 -04:00
#if REFRACTION_USE_PIXEL_NORMAL_OFFSET
half3 ViewVertexNormal = TransformTangentVectorToView(MaterialParameters, float3(0, 0, 1));
2019-09-23 20:39:36 -04:00
// Treat refraction of 1 as no refraction, to be consistent with IOR mode
2022-11-28 16:37:24 -05:00
float2 ViewportUVDistortion = (ViewVertexNormal.xy - ViewNormal.xy) * (GetMaterialRefractionPixelNormalStrength(RefractionData) - 1);
2022-12-02 03:49:35 -05:00
2022-11-28 16:37:24 -05:00
#elif REFRACTION_USE_INDEX_OF_REFRACTION
2019-09-20 10:28:29 -04:00
// we assume the camera is in air
float AirIOR = 1.0f;
2023-09-01 15:06:19 -04:00
#if REFRACTION_ROOT_NODE_OVERRIDES_DEFAULT || SUBSTRATE_OPTIMIZED_UNLIT
2022-12-02 03:49:35 -05:00
float MaterialIOR = GetMaterialRefractionIOR(RefractionData);
#else
float MaterialIOR = InMaterialIOR;
#endif
float2 ViewportUVDistortion = ViewNormal.xy * (MaterialIOR - AirIOR);
2022-11-28 16:37:24 -05:00
#elif REFRACTION_USE_2D_OFFSET
float2 ViewportUVDistortion = GetMaterialRefraction2DOffset(RefractionData);
2022-12-02 03:49:35 -05:00
#elif REFRACTION_USE_NONE
float2 ViewportUVDistortion = 0.0f;
2022-11-28 16:37:24 -05:00
#else
#error Unkown refraction mode.
2019-09-20 10:28:29 -04:00
#endif
float2 BufferUVDistortion = ViewportUVDistortion * ResolvedView.ViewSizeAndInvSize.xy * ResolvedView.BufferSizeAndInvSize.zw;
2023-02-15 10:21:34 -05:00
// Clip if the distortion distance (squared) is too small to be noticed.
// This will result in a less expensive apply pass since the clipped pixels won't set stencil to pass.
// We only clip if the distortion is less than the size of a pixel of the unscaled viewport, i.e. dynamic resolution = 100%, to ensure a good reconstruction.
const float2 FullResolutionDistortionPixelSize = ResolvedView.BufferSizeAndInvSize.zw;
if (TryToClip &&
all(abs(BufferUVDistortion) < FullResolutionDistortionPixelSize))
2019-09-20 10:28:29 -04:00
{
2023-02-15 10:21:34 -05:00
clip(-1.0f);
2019-09-20 10:28:29 -04:00
}
2019-09-24 13:18:25 -04:00
// When ISR is enabled we store two FOVs in the DistortionParameters and compute the aspect ratio here
2019-09-20 10:28:29 -04:00
#if INSTANCED_STEREO
2019-11-14 07:02:34 -05:00
float InvTanHalfFov = DistortionParameters[EyeIndex];
2019-09-24 13:18:25 -04:00
float Ratio = DistortionParameters.z / DistortionParameters.w;
2019-09-20 10:28:29 -04:00
#else
2019-09-24 13:18:25 -04:00
float InvTanHalfFov = DistortionParameters.x;
float Ratio = DistortionParameters.y;
2019-09-20 10:28:29 -04:00
#endif
2020-01-24 18:07:01 -05:00
// InvTanHalfFov only apply a correction for the distortion to be the same in screen space space whatever the FoV is (to make it consistent accross player setup).
// However without taking depth into account, the distortion will actually be stronger the further away the camera is from the distortion surface.
// So when zoomed-in the distortion will be higher than expected.
// To fix this, a scale of 100/SurfaceDepth would be a good approximation to make the distortion properly scaled when the surface is zoomed in and/or further away (with distortion authored at 1meter being the reference strength)
2019-09-20 10:28:29 -04:00
// Fix for Fov and aspect.
float2 FovFix = float2(InvTanHalfFov, Ratio*InvTanHalfFov);
//A fudge factor scale to bring values close to what they would have been under usual circumstances prior to this change.
const float OffsetFudgeFactor = 0.00023;
2019-09-24 13:18:25 -04:00
BufferUVDistortion *= DistortionParameters.zw * float2(OffsetFudgeFactor, -OffsetFudgeFactor) * FovFix;
2019-09-20 10:28:29 -04:00
return BufferUVDistortion;
}
void PostProcessUVDistortion(
in FMaterialPixelParameters MaterialParameters, in FPixelMaterialInputs PixelMaterialInputs,
2022-11-28 16:37:24 -05:00
in float DistortSceneDepth, inout float2 BufferUVDistortion, in FMaterialRefractionData RefractionData)
2019-09-20 10:28:29 -04:00
{
// Soft thresholding
2022-11-28 16:37:24 -05:00
float Bias = -RefractionData.RefractionDepthBias;
2019-09-20 10:28:29 -04:00
float Range = clamp(abs(Bias * 0.5f), 0, 50);
float Z = DistortSceneDepth;
float ZCompare = MaterialParameters.ScreenPosition.w;
float InvWidth = 1.0f / max(1.0f, Range);
BufferUVDistortion *= saturate((Z - ZCompare) * InvWidth + Bias);
//Scale up for better precision in low/subtle refractions at the expense of artefacts at higher refraction.
static const half DistortionScaleBias = 4.0f;
BufferUVDistortion *= DistortionScaleBias;
}