|
|
|
|
|
|
// ---------------------------------------------------------------------------- |
|
|
|
|
|
|
|
// Z buffer to linear 0..1 depth (0 at near plane, 1 at far plane). |
|
|
|
// Does not correctly handle oblique view frustums. |
|
|
|
// Does NOT correctly handle oblique view frustums. |
|
|
|
// Does NOT work with orthographic projection. |
|
|
|
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f } |
|
|
|
float Linear01DepthFromNear(float depth, float4 zBufferParam) |
|
|
|
{ |
|
|
|
|
|
|
// Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane). |
|
|
|
// Does not correctly handle oblique view frustums. |
|
|
|
// Does NOT work with orthographic projections. |
|
|
|
// Does NOT correctly handle oblique view frustums. |
|
|
|
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f } |
|
|
|
float Linear01Depth(float depth, float4 zBufferParam) |
|
|
|
{ |
|
|
|
|
|
|
// Z buffer to linear depth. |
|
|
|
// Does not correctly handle oblique view frustums. |
|
|
|
// Does NOT correctly handle oblique view frustums. |
|
|
|
// Does NOT work with orthographic projection. |
|
|
|
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f } |
|
|
|
float LinearEyeDepth(float depth, float4 zBufferParam) |
|
|
|
{ |
|
|
|
|
|
|
// Z buffer to linear depth. |
|
|
|
// Correctly handles oblique view frustums. Only valid for projection matrices! |
|
|
|
// Correctly handles oblique view frustums. |
|
|
|
// Does NOT work with orthographic projection. |
|
|
|
// The view space uses a right-handed coordinate system. |
|
|
|
return -viewSpaceZ; |
|
|
|
|
|
|
|
// If the matrix is right-handed, we have to flip the Z axis to get a positive value. |
|
|
|
return abs(viewSpaceZ); |
|
|
|
// Correctly handles oblique view frustums. |
|
|
|
// Works in all cases. |
|
|
|
float LinearEyeDepth(float3 positionWS, float4x4 viewProjMatrix) |
|
|
|
// Assumes that the 'positionWS' is in front of the camera. |
|
|
|
float LinearEyeDepth(float3 positionWS, float4x4 viewMatrix) |
|
|
|
return mul(viewProjMatrix, float4(positionWS, 1.0)).w; |
|
|
|
float viewSpaceZ = mul(viewMatrix, float4(positionWS, 1.0)).z; |
|
|
|
|
|
|
|
// If the matrix is right-handed, we have to flip the Z axis to get a positive value. |
|
|
|
return abs(viewSpaceZ); |
|
|
|
} |
|
|
|
|
|
|
|
// 'z' is the view space Z position (linear depth). |
|
|
|
|
|
|
return mul(clipSpaceTransform, float4(position, 1.0)); |
|
|
|
} |
|
|
|
|
|
|
|
// The returned Z value is the depth buffer value (and NOT linear view space Z value). |
|
|
|
// Use case examples: |
|
|
|
// (position = positionCS) => (clipSpaceTransform = use default) |
|
|
|
// (position = positionVS) => (clipSpaceTransform = UNITY_MATRIX_P) |
|
|
|
|
|
|
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float linearDepth, float3 positionWS, uint2 tileCoord) |
|
|
|
{ |
|
|
|
PositionInputs posInput = GetPositionInput(positionSS, invScreenSize, tileCoord); |
|
|
|
posInput.deviceDepth = deviceDepth; |
|
|
|
posInput.linearDepth = linearDepth; |
|
|
|
posInput.positionWS = positionWS; |
|
|
|
posInput.positionWS = positionWS; |
|
|
|
posInput.deviceDepth = deviceDepth; |
|
|
|
posInput.linearDepth = linearDepth; |
|
|
|
|
|
|
|
return posInput; |
|
|
|
} |
|
|
|
|
|
|
// From deferred or compute shader |
|
|
|
// depth must be the depth from the raw depth buffer. This allow to handle all kind of depth automatically with the inverse view projection matrix. |
|
|
|
// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed. |
|
|
|
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix, uint2 tileCoord) |
|
|
|
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, |
|
|
|
float4x4 invViewProjMatrix, float4x4 viewMatrix, |
|
|
|
uint2 tileCoord) |
|
|
|
posInput.deviceDepth = deviceDepth; |
|
|
|
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionNDC, deviceDepth, invViewProjMatrix); |
|
|
|
|
|
|
|
// The compiler should optimize this (less expensive than reconstruct depth VS from depth buffer) |
|
|
|
posInput.linearDepth = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)).w; |
|
|
|
posInput.positionWS = ComputeWorldSpacePosition(posInput.positionNDC, deviceDepth, invViewProjMatrix); |
|
|
|
posInput.deviceDepth = deviceDepth; |
|
|
|
posInput.linearDepth = LinearEyeDepth(posInput.positionWS, viewMatrix); |
|
|
|
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, float4x4 invViewProjMatrix, float4x4 viewProjMatrix) |
|
|
|
PositionInputs GetPositionInput(float2 positionSS, float2 invScreenSize, float deviceDepth, |
|
|
|
float4x4 invViewProjMatrix, float4x4 viewMatrix) |
|
|
|
return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewProjMatrix, uint2(0, 0)); |
|
|
|
return GetPositionInput(positionSS, invScreenSize, deviceDepth, invViewProjMatrix, viewMatrix, uint2(0, 0)); |
|
|
|
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float4x4 viewProjMatrix, inout PositionInputs posInput) |
|
|
|
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, float3 viewForwardDir, float4x4 viewProjMatrix, inout PositionInputs posInput) |
|
|
|
posInput.deviceDepth = ComputeNormalizedDeviceCoordinatesWithZ(posInput.positionWS, viewProjMatrix).z; |
|
|
|
float4 positionCS = mul(viewProjMatrix, float4(posInput.positionWS, 1.0)); |
|
|
|
posInput.linearDepth = positionCS.w; |
|
|
|
posInput.deviceDepth = positionCS.z / positionCS.w; |
|
|
|
// Transform the displacement along the view vector to the displacement along the forward vector. |
|
|
|
// Use abs() to make sure we get the sign right. |
|
|
|
// 'depthOffsetVS' applies in the direction away from the camera. |
|
|
|
posInput.linearDepth += depthOffsetVS * abs(dot(V, viewForwardDir)); |
|
|
|
} |
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------- |
|
|
|