Files
UnrealEngineUWP/Engine/Shaders/GlobalDistanceFieldShared.usf
Mark Satterthwaite 977542aeaa Merging general rendering & shader changes necessary to support desktop Metal.
reviewedby michael.trepka, rolando.caloca, lee.clark

[CL 2670859 by Mark Satterthwaite in Main branch]
2015-08-27 10:11:22 -04:00

228 lines
10 KiB
Plaintext

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
GlobalDistanceFieldShared.usf
=============================================================================*/
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
float MaxGlobalDistance;
//@todo - get the clipmap branches to compile under gl
#if SM5_PROFILE || PS4_PROFILE
// Must match C++
#define MAX_GLOBAL_DF_CLIPMAPS 4
Texture3D GlobalDistanceFieldTexture0;
Texture3D GlobalDistanceFieldTexture1;
Texture3D GlobalDistanceFieldTexture2;
Texture3D GlobalDistanceFieldTexture3;
SamplerState GlobalDistanceFieldSampler0;
SamplerState GlobalDistanceFieldSampler1;
SamplerState GlobalDistanceFieldSampler2;
SamplerState GlobalDistanceFieldSampler3;
float4 GlobalVolumeCenterAndExtent[MAX_GLOBAL_DF_CLIPMAPS];
float4 GlobalVolumeWorldToUVAddAndMul[MAX_GLOBAL_DF_CLIPMAPS];
float GlobalVolumeDimension;
float GlobalVolumeTexelSize;
float4 SampleGlobalDistanceField(int ClipmapIndex, float3 UV)
{
if (ClipmapIndex == 0)
{
return Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, UV, 0);
}
else if (ClipmapIndex == 1)
{
return Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, UV, 0);
}
else if (ClipmapIndex == 2)
{
return Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, UV, 0);
}
else
{
return Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, UV, 0);
}
}
float3 ComputeGlobalUV(float3 WorldPosition, uint ClipmapIndex)
{
//return ((WorldPosition - GlobalVolumeCenterAndExtent[ClipmapIndex].xyz + GlobalVolumeScollOffset[ClipmapIndex].xyz) / (GlobalVolumeCenterAndExtent[ClipmapIndex].w * 2) + .5f);
float4 WorldToUVAddAndMul = GlobalVolumeWorldToUVAddAndMul[ClipmapIndex];
return WorldPosition * WorldToUVAddAndMul.www + WorldToUVAddAndMul.xyz;
}
float GetDistanceToNearestSurfaceGlobalClipmap(float3 WorldPosition, uint ClipmapIndex)
{
float3 GlobalUV = ComputeGlobalUV(WorldPosition, ClipmapIndex);
float DistanceToSurface = 0;
if (ClipmapIndex == 0)
{
DistanceToSurface = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, GlobalUV, 0).x;
}
else if (ClipmapIndex == 1)
{
DistanceToSurface = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, GlobalUV, 0).x;
}
else if (ClipmapIndex == 2)
{
DistanceToSurface = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, GlobalUV, 0).x;
}
else if (ClipmapIndex == 3)
{
DistanceToSurface = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, GlobalUV, 0).x;
}
return DistanceToSurface;
}
float GetDistanceToNearestSurfaceGlobal(float3 WorldPosition)
{
float DistanceToSurface = MaxGlobalDistance;
float DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[0].xyz, GlobalVolumeCenterAndExtent[0].www, WorldPosition);
//@todo - would be nice to atlas to get rid of branches and multiple samplers but the partial update scrolling relies on wrap addressing
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[0].w * GlobalVolumeTexelSize)
{
DistanceToSurface = GetDistanceToNearestSurfaceGlobalClipmap(WorldPosition, 0);
}
else
{
DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[1].xyz, GlobalVolumeCenterAndExtent[1].www, WorldPosition);
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[1].w * GlobalVolumeTexelSize)
{
DistanceToSurface = GetDistanceToNearestSurfaceGlobalClipmap(WorldPosition, 1);
}
else
{
DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[2].xyz, GlobalVolumeCenterAndExtent[2].www, WorldPosition);
float DistanceFromLastClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[3].xyz, GlobalVolumeCenterAndExtent[3].www, WorldPosition);
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[2].w * GlobalVolumeTexelSize)
{
DistanceToSurface = GetDistanceToNearestSurfaceGlobalClipmap(WorldPosition, 2);
}
else if (DistanceFromLastClipmap > GlobalVolumeCenterAndExtent[3].w * GlobalVolumeTexelSize)
{
DistanceToSurface = GetDistanceToNearestSurfaceGlobalClipmap(WorldPosition, 3);
}
}
}
return DistanceToSurface;
}
float3 GetDistanceFieldGradientGlobalClipmap(float3 WorldPosition, uint ClipmapIndex)
{
float3 GlobalUV = ComputeGlobalUV(WorldPosition, ClipmapIndex);
float R = 0;
float L = 0;
float F = 0;
float B = 0;
float U = 0;
float D = 0;
if (ClipmapIndex == 0)
{
R = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x + GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
L = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x - GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
F = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x, GlobalUV.y + GlobalVolumeTexelSize, GlobalUV.z), 0).x;
B = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x, GlobalUV.y - GlobalVolumeTexelSize, GlobalUV.z), 0).x;
U = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z + GlobalVolumeTexelSize), 0).x;
D = Texture3DSampleLevel(GlobalDistanceFieldTexture0, GlobalDistanceFieldSampler0, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z - GlobalVolumeTexelSize), 0).x;
}
else if (ClipmapIndex == 1)
{
R = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x + GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
L = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x - GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
F = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x, GlobalUV.y + GlobalVolumeTexelSize, GlobalUV.z), 0).x;
B = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x, GlobalUV.y - GlobalVolumeTexelSize, GlobalUV.z), 0).x;
U = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z + GlobalVolumeTexelSize), 0).x;
D = Texture3DSampleLevel(GlobalDistanceFieldTexture1, GlobalDistanceFieldSampler1, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z - GlobalVolumeTexelSize), 0).x;
}
else if (ClipmapIndex == 2)
{
R = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x + GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
L = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x - GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
F = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x, GlobalUV.y + GlobalVolumeTexelSize, GlobalUV.z), 0).x;
B = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x, GlobalUV.y - GlobalVolumeTexelSize, GlobalUV.z), 0).x;
U = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z + GlobalVolumeTexelSize), 0).x;
D = Texture3DSampleLevel(GlobalDistanceFieldTexture2, GlobalDistanceFieldSampler2, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z - GlobalVolumeTexelSize), 0).x;
}
else if (ClipmapIndex == 3)
{
R = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x + GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
L = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x - GlobalVolumeTexelSize, GlobalUV.y, GlobalUV.z), 0).x;
F = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x, GlobalUV.y + GlobalVolumeTexelSize, GlobalUV.z), 0).x;
B = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x, GlobalUV.y - GlobalVolumeTexelSize, GlobalUV.z), 0).x;
U = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z + GlobalVolumeTexelSize), 0).x;
D = Texture3DSampleLevel(GlobalDistanceFieldTexture3, GlobalDistanceFieldSampler3, float3(GlobalUV.x, GlobalUV.y, GlobalUV.z - GlobalVolumeTexelSize), 0).x;
}
float Extent = GlobalVolumeCenterAndExtent[ClipmapIndex].w;
float3 Gradient = .5f * float3(R - L, F - B, U - D) / Extent;
return Gradient;
}
float3 GetDistanceFieldGradientGlobal(float3 WorldPosition)
{
float3 Gradient = float3(0, 0, .001f);
float DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[0].xyz, GlobalVolumeCenterAndExtent[0].www, WorldPosition);
// Don't sample near the border to avoid sampling out of bounds during partial differencing
float BorderTexels = GlobalVolumeTexelSize * 4;
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[0].w * BorderTexels)
{
Gradient = GetDistanceFieldGradientGlobalClipmap(WorldPosition, 0);
}
else
{
DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[1].xyz, GlobalVolumeCenterAndExtent[1].www, WorldPosition);
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[1].w * BorderTexels)
{
Gradient = GetDistanceFieldGradientGlobalClipmap(WorldPosition, 1);
}
else
{
DistanceFromClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[2].xyz, GlobalVolumeCenterAndExtent[2].www, WorldPosition);
float DistanceFromLastClipmap = ComputeDistanceFromBoxToPointInside(GlobalVolumeCenterAndExtent[3].xyz, GlobalVolumeCenterAndExtent[3].www, WorldPosition);
BRANCH
if (DistanceFromClipmap > GlobalVolumeCenterAndExtent[2].w * BorderTexels)
{
Gradient = GetDistanceFieldGradientGlobalClipmap(WorldPosition, 2);
}
else if (DistanceFromLastClipmap > GlobalVolumeCenterAndExtent[3].w * BorderTexels)
{
Gradient = GetDistanceFieldGradientGlobalClipmap(WorldPosition, 3);
}
}
}
return Gradient;
}
#else
float GetDistanceToNearestSurfaceGlobal(float3 WorldPosition)
{
return MaxGlobalDistance;
}
float3 GetDistanceFieldGradientGlobal(float3 WorldPosition)
{
return float3(0, 0, .001f);
}
#endif
#endif // FEATURE_LEVEL >= FEATURE_LEVEL_SM5