// unsigned integer bit field extract implementation
uint BitFieldExtract(uint data, uint numBits, uint offset)
{
uint mask = UINT_MAX >> (32u - numBits);
uint mask = 0xFFFFFFFFu >> (32u - numBits);
return (data >> offset) & mask;
}
#endif // INTRINSIC_BITFIELD_EXTRACT
#endif // INTRINSIC_CUBEMAP_FACE_ID
// ----------------------------------------------------------------------------
// Common math functions
// Common math definition and fastmath function
#define PI 3.14159265359
#define TWO_PI 6.28318530718
#define FOUR_PI 12.56637061436
#define INV_PI 0.31830988618
#define INV_TWO_PI 0.15915494309
#define INV_FOUR_PI 0.07957747155
#define HALF_PI 1.57079632679
#define INV_HALF_PI 0.636619772367
#define INFINITY asfloat(0x7F800000)
#define LOG2_E 1.44269504089
#define FLT_EPSILON 1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
#define HFLT_MIN 0.00006103515625 // 2^14 it is the same for 10, 11 and 16bit float. ref: https://www.khronos.org/opengl/wiki/Small_Float_Formats
float DegToRad(float deg)
{
return deg * (PI / 180.0);
// Using pow often result to a warning like this
// "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"
// PositivePow remove this warning when you know the value is positive and avoid inf/NAN.
TEMPLATE_2_FLT(PositivePow, base, power, return pow(max(abs(base), FLT_EPS), power))
TEMPLATE_2_FLT(PositivePow, base, power, return pow(max(abs(base), FLT_EPSILON ), power))
// Ref: https://twitter.com/SebAaltonen/status/878250919879639040
// 2 mads (mad_sat and mad), faster than regular sign
// Z buffer to linear depth.
// Correctly handles oblique view frustums. Only valid for projection matrices!
// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
float LinearEyeDepth(float2 positionSS, float deviceDepth, float4 invProjParam)
float LinearEyeDepth(float2 positionSS, float depthRaw, float4 invProjParam)
float4 positionCS = float4(positionSS * 2.0 - 1.0, deviceDepth, 1.0);
float4 positionCS = float4(positionSS * 2.0 - 1.0, depthRaw, 1.0);
}
// Z buffer to linear depth.
// Correctly handles oblique view frustums.
// Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
float LinearEyeDepth(float3 positionWS, float3x3 viewProjMatrix)
{
return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
}
// ----------------------------------------------------------------------------
return positionSS;
}
float4 ComputeClipSpacePosition(float2 positionSS, float deviceDe pth)
float4 ComputeClipSpacePosition(float2 positionSS, float depthRaw )
return float4(positionSS * 2.0 - 1.0, deviceDe pth, 1.0);
return float4(positionSS * 2.0 - 1.0, depthRaw , 1.0);
float3 ComputeViewSpacePosition(float2 positionSS, float deviceDe pth, float4x4 invProjMatrix)
float3 ComputeViewSpacePosition(float2 positionSS, float depthRaw , float4x4 invProjMatrix)
float4 positionCS = ComputeClipSpacePosition(positionSS, deviceDe pth);
float4 positionCS = ComputeClipSpacePosition(positionSS, depthRaw );
float4 positionVS = mul(invProjMatrix, positionCS);
// The view space uses a right-handed coordinate system.
positionVS.z = -positionVS.z;
float3 ComputeWorldSpacePosition(float2 positionSS, float deviceDepth, float4x4 invViewProjMatrix)
float3 ComputeWorldSpacePosition(float2 positionSS, float depthRaw, float4x4 invViewProjMatrix)
float4 positionCS = ComputeClipSpacePosition(positionSS, deviceDepth);
float4 positionCS = ComputeClipSpacePosition(positionSS, depthRaw);
float4 hpositionWS = mul(invViewProjMatrix, positionCS);
return hpositionWS.xyz / hpositionWS.w;
}
struct PositionInputs
{
// TODO: improve the naming convention.
// Some options:
// positionNDC, positionSS, tileCoordSS
// pixelCoordUV, pixelCoordSS, tileCoordSS
// pixelCoordSS, pixelIndexSS, tileIndexSS
float3 positionWS; // World space position (could be camera-relative)
float2 positionSS; // Screen space pixel position : [0, 1) (with the half-pixel offset)
uint2 unPositionSS; // Screen space pixel index : [0, NumPixels)
uint2 unTileCoord; // Screen space tile index : [0, NumTiles)
float deviceDepth; // Depth from the depth buffer : [0, 1]
float linearDepth; // View space Z coordinate : [Near, Far]
// Normalize screen position (offset by 0.5)
float2 positionSS;
// Unormalize screen position (offset by 0.5)
uint2 unPositionSS;
uint2 unTileCoord;
float depthRaw; // raw depth from depth buffer
float depthVS;
float3 positionWS;
};
// This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.
}
// From forward
// deviceDepth and linearDepth come directly from .zw of SV_Position
void UpdatePositionInput(float deviceDepth, float linearDepth, float3 positionWS, inout PositionInputs posInput)
// depthRaw and depthVS come directly form .zw of SV_Position
void UpdatePositionInput(float depthRaw, float depthVS, float3 positionWS, inout PositionInputs posInput)
posInput.deviceDepth = deviceDepth;
posInput.linearDepth = linearDepth;
posInput.positionWS = positionWS;
posInput.depthRaw = depthRaw;
posInput.depthVS = depthVS;
posInput.positionWS = positionWS;
void UpdatePositionInput(float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, inout PositionInputs posInput)
void UpdatePositionInput(float depthRaw, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, inout PositionInputs posInput)
posInput.deviceDepth = deviceDepth;
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionSS, deviceDepth, invViewProjMatrix);
posInput.depthRaw = depthRaw;
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionSS, depthRaw, invViewProjMatrix);
posInput.linearDepth = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
posInput.depthVS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w;
}
// The view direction 'V' points towards the camera.
posInput.positionWS += depthOffsetVS * (-V);
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0));
posInput.linearDepth = positionCS.w;
posInput.deviceDe pth = positionCS.z / positionCS.w;
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0));
posInput.depthVS = positionCS.w;
posInput.depthRaw = positionCS.z / positionCS.w;
}
// ----------------------------------------------------------------------------