浏览代码

HiZ: Raymarch behind surfaces

/main
Frédéric Vauchelles 6 年前
当前提交
576ebd36
共有 5 个文件被更改,包括 156 次插入98 次删除
  1. 46
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs
  2. 21
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs.hlsl
  3. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader
  4. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/ScreenSpaceReflection.cs
  5. 175
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/ScreenSpaceTracing.hlsl

46
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs


[GenerateHLSL]
public struct ScreenSpaceTracingDebug
{
// Used to debug SSRay model
// Used to debug SSRay model
public uint loopStartPositionSSX; // Proxy, HiZ
public uint loopStartPositionSSY; // Proxy, HiZ
public float loopStartLinearDepth; // Proxy, HiZ
public Vector3 loopRayDirectionSS; // HiZ
public uint loopStartPositionSSX; // Proxy, HiZ, Linear
public uint loopStartPositionSSY; // Proxy, HiZ, Linear
public float loopStartLinearDepth; // Proxy, HiZ, Linear
public Vector3 loopRayDirectionSS; // HiZ, Linear
public uint loopIterationMax; // HiZ
public uint loopIterationMax; // HiZ, Linear
// 9x32 bits
public Vector3 iterationPositionSS; // HiZ
public uint iterationMipLevel; // HiZ
public uint iteration; // HiZ
public float iterationLinearDepthBuffer; // HiZ
// 11x32 bits
public Vector3 iterationPositionSS; // HiZ, Linear
public uint iterationMipLevel; // HiZ, Linear
public uint iteration; // HiZ, Linear
public float iterationLinearDepthBufferMin; // HiZ, Linear
public float iterationLinearDepthBufferMax; // HiZ, Linear
public float iterationLinearDepthBufferMinThickness; // HiZ, Linear
public uint iterationCellSizeW; // HiZ
public uint iterationCellSizeH; // HiZ
public uint iterationCellSizeW; // HiZ, Linear
public uint iterationCellSizeH; // HiZ, Linear
public int endHitSuccess; // Proxy, HiZ
public float endLinearDepth; // Proxy, HiZ
public uint endPositionSSX; // Proxy, HiZ
public uint endPositionSSY; // Proxy, HiZ
public int endHitSuccess; // Proxy, HiZ, Linear
public float endLinearDepth; // Proxy, HiZ, Linear
public uint endPositionSSX; // Proxy, HiZ, Linear
public uint endPositionSSY; // Proxy, HiZ, Linear
// 0x32 bits (padding)
// 2x32 bits (padding)
public Vector2 padding;
public bool intersectDepthBuffer { get { return (1.0f / iterationPositionSS.z) >= iterationLinearDepthBufferMin && (1.0f / iterationPositionSS.z) <= iterationLinearDepthBufferMinThickness; } }
}
public class DebugDisplaySettings

new DebugUI.Value { displayName = "Iteration", getter = () => string.Format("{0}/{1}", screenSpaceTracingDebugData.iteration, screenSpaceTracingDebugData.loopIterationMax) },
new DebugUI.Value { displayName = "Position SS", getter = () => new Vector2(screenSpaceTracingDebugData.iterationPositionSS.x, screenSpaceTracingDebugData.iterationPositionSS.y) },
new DebugUI.Value { displayName = "Depth", getter = () => 1f / screenSpaceTracingDebugData.iterationPositionSS.z },
new DebugUI.Value { displayName = "Depth Buffer", getter = () => screenSpaceTracingDebugData.iterationLinearDepthBuffer },
new DebugUI.Value { displayName = "Depth Buffer Min/Min + Thickness/Max", getter = () => string.Format("{0}/{1}/{2}", screenSpaceTracingDebugData.iterationLinearDepthBufferMin, screenSpaceTracingDebugData.iterationLinearDepthBufferMinThickness, screenSpaceTracingDebugData.iterationLinearDepthBufferMax) },
new DebugUI.Value { displayName = "Intersect Depth Buffer", getter = () => screenSpaceTracingDebugData.intersectDepthBuffer },
new DebugUI.Value { displayName = "Mip Level", getter = () => screenSpaceTracingDebugData.iterationMipLevel },
new DebugUI.Value { displayName = "Cell Id", getter = () => screenSpaceTracingDebugData.iterationCellId },
new DebugUI.Value { displayName = "Cell Size", getter = () => screenSpaceTracingDebugData.iterationCellSize },

new DebugUI.Value { displayName = "Iteration", getter = () => string.Format("{0}/{1}", screenSpaceTracingDebugData.iteration, screenSpaceTracingDebugData.loopIterationMax) },
new DebugUI.Value { displayName = "Position SS", getter = () => new Vector2(screenSpaceTracingDebugData.iterationPositionSS.x, screenSpaceTracingDebugData.iterationPositionSS.y) },
new DebugUI.Value { displayName = "Depth", getter = () => 1f / screenSpaceTracingDebugData.iterationPositionSS.z },
new DebugUI.Value { displayName = "Depth Buffer", getter = () => screenSpaceTracingDebugData.iterationLinearDepthBuffer },
new DebugUI.Value { displayName = "Depth Buffer Min/Min + Thickness/Max", getter = () => string.Format("{0}/{1}/{2}", screenSpaceTracingDebugData.iterationLinearDepthBufferMin, screenSpaceTracingDebugData.iterationLinearDepthBufferMinThickness, screenSpaceTracingDebugData.iterationLinearDepthBufferMax) },
new DebugUI.Value { displayName = "Intersect Depth Buffer", getter = () => screenSpaceTracingDebugData.intersectDepthBuffer },
new DebugUI.Value { displayName = "Mip Level", getter = () => screenSpaceTracingDebugData.iterationMipLevel },
new DebugUI.Value { displayName = "Cell Id", getter = () => screenSpaceTracingDebugData.iterationCellId },
new DebugUI.Value { displayName = "Cell Size", getter = () => screenSpaceTracingDebugData.iterationCellSize },

21
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugDisplay.cs.hlsl


float3 iterationPositionSS;
uint iterationMipLevel;
uint iteration;
float iterationLinearDepthBuffer;
float iterationLinearDepthBufferMin;
float iterationLinearDepthBufferMax;
float iterationLinearDepthBufferMinThickness;
int iterationIntersectionKind;
uint iterationCellSizeW;
uint iterationCellSizeH;

float endLinearDepth;
uint endPositionSSX;
uint endPositionSSY;
float2 padding;
};
//

{
return value.iteration;
}
float GetIterationLinearDepthBuffer(ScreenSpaceTracingDebug value)
float GetIterationLinearDepthBufferMin(ScreenSpaceTracingDebug value)
{
return value.iterationLinearDepthBufferMin;
}
float GetIterationLinearDepthBufferMax(ScreenSpaceTracingDebug value)
{
return value.iterationLinearDepthBufferMax;
}
float GetIterationLinearDepthBufferMinThickness(ScreenSpaceTracingDebug value)
return value.iterationLinearDepthBuffer;
return value.iterationLinearDepthBufferMinThickness;
}
int GetIterationIntersectionKind(ScreenSpaceTracingDebug value)
{

uint GetEndPositionSSY(ScreenSpaceTracingDebug value)
{
return value.endPositionSSY;
}
float2 GetPadding(ScreenSpaceTracingDebug value)
{
return value.padding;
}

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Debug/DebugFullScreen.shader


ScreenSpaceTracingDebug debug = _DebugScreenSpaceTracingData[0];
// Fetch Depth Buffer and Position Inputs
const float deviceDepth = LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, int2(input.positionCS.xy) >> debug.iterationMipLevel, debug.iterationMipLevel).r;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, deviceDepth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
const float2 deviceDepth = LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, int2(input.positionCS.xy) >> debug.iterationMipLevel, debug.iterationMipLevel).rg;
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, deviceDepth.r, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP);
float4 col = float4(0, 0, 0, 1);

const float raySegmentSDF = clamp(1 - distanceToRaySegment, 0, 1);
float cellSDF = 0;
float debugLinearDepth = LinearEyeDepth(deviceDepth, _ZBufferParams);;
float2 debugLinearDepth = float2(LinearEyeDepth(deviceDepth.r, _ZBufferParams), LinearEyeDepth(deviceDepth.g, _ZBufferParams));
if (debug.tracingModel == PROJECTIONMODEL_HI_Z
|| debug.tracingModel == PROJECTIONMODEL_LINEAR)
{

col.rgb = col.rgb * w + float3(1, 1, 1) * (1 - w);
if (_ShowDepthPyramidDebug == 1)
color.rgb = frac(debugLinearDepth * 0.1);
color.rgb = float3(frac(debugLinearDepth * 0.1), 0.0);
col = float4(col.rgb * col.a + color.rgb, 1);

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/ScreenSpaceReflection.cs


rayMaxIterationsID = HDShaderIDs._SSReflectionRayMaxIterations;
rayDepthSuccessBiasID = HDShaderIDs._SSReflectionRayDepthSuccessBias;
screenWeightDistanceID = HDShaderIDs._SSReflectionInvScreenWeightDistance;
rayMaxScreenDistanceID = HDShaderIDs._SSReflectionInvScreenWeightDistance;
rayBlendScreenDistanceID = HDShaderIDs._SSReflectionInvScreenWeightDistance;
rayMaxScreenDistanceID = HDShaderIDs._SSReflectionRayMaxScreenDistance;
rayBlendScreenDistanceID = HDShaderIDs._SSReflectionRayBlendScreenDistance;
}
public override void PushShaderParameters(CommandBuffer cmd)

175
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Reflection/ScreenSpaceTracing.hlsl


// Check whether the depth of the ray is above the sampled depth
// Arguments are inversed linear depth
bool IsPositionAboveDepth(float invRayDepth, float invLinearDepth)
bool IsPositionAboveDepth(float invRayDepth, float2 invLinearDepth)
return invRayDepth > invLinearDepth;
return invRayDepth > invLinearDepth.r;
float LoadDepth(float2 positionSS, int level)
float2 LoadDepth(float2 positionSS, int level)
float pyramidDepth = LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, int2(positionSS.xy) >> level, level).r;
float linearDepth = LinearEyeDepth(pyramidDepth, _ZBufferParams);
float2 pyramidDepth = LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, int2(positionSS.xy) >> level, level).rg;
float2 linearDepth = float2(LinearEyeDepth(pyramidDepth.r, _ZBufferParams), LinearEyeDepth(pyramidDepth.g, _ZBufferParams));
float LoadInvDepth(float2 positionSS, int level)
float2 LoadInvDepth(float2 positionSS, int level)
float linearDepth = LoadDepth(positionSS, level);
float invLinearDepth = 1 / linearDepth;
float2 linearDepth = LoadDepth(positionSS, level);
float2 invLinearDepth = 1 / linearDepth;
return invLinearDepth;
}

float CalculateHitWeight(
ScreenSpaceRayHit hit,
float2 startPositionSS,
float invLinearDepth,
float2 invLinearDepth,
float settingsRayDepthSuccessBias,
float settingsRayMaxScreenDistance,
float settingsRayBlendScreenDistance

float thicknessWeight = (1 + ((1 / invLinearDepth) - hit.linearDepth) / settingsRayDepthSuccessBias);
float thicknessWeight = (1 + ((1 / invLinearDepth.r) - hit.linearDepth) / settingsRayDepthSuccessBias);
return thicknessWeight;
float2 screenDistanceNDC = abs(hit.positionSS.xy - startPositionSS) * _ScreenSize.zw;
float2 screenDistanceWeights = clamp((settingsRayMaxScreenDistance - screenDistanceNDC) / settingsRayBlendScreenDistance, 0, 1);
float screenDistanceWeight = min(screenDistanceWeights.x, screenDistanceWeights.y);
// float2 screenDistanceNDC = abs(hit.positionSS.xy - startPositionSS) * _ScreenSize.zw;
// float2 screenDistanceWeights = clamp((settingsRayMaxScreenDistance - screenDistanceNDC) / settingsRayBlendScreenDistance, 0, 1);
// float screenDistanceWeight = min(screenDistanceWeights.x, screenDistanceWeights.y);
return thicknessWeight * screenDistanceWeight;
}
bool IsRaymarchingTooFar(
float2 startPositionSS,
float2 positionSS
)
{
// return thicknessWeight * screenDistanceWeight;
}
#ifdef DEBUG_DISPLAY

#ifdef DEBUG_DISPLAY
float3 debugIterationPositionSS = positionSS;
float debugIterationLinearDepthBuffer = 0;
float debugIterationLinearDepthBufferMin = 0;
float debugIterationLinearDepthBufferMinThickness = 0;
float debugIterationLinearDepthBufferMax = 0;
float invLinearDepth = 0;
float2 invLinearDepth = float2(0.0, 0.0);
for (iteration = 0u; iteration < maxIterations; ++iteration)
{

if (input.debug && _DebugStep >= int(iteration))
{
debugIterationPositionSS = positionSS;
debugIterationLinearDepthBuffer = 1 / invLinearDepth;
debugIterationLinearDepthBufferMin = 1 / invLinearDepth.r;
debugIterationLinearDepthBufferMinThickness = 1 / invLinearDepth.r + settingsRayDepthSuccessBias;
debugIterationLinearDepthBufferMax = 1 / invLinearDepth.g;
debugIteration = iteration;
}
#endif

ScreenSpaceTracingDebug debug;
ZERO_INITIALIZE(ScreenSpaceTracingDebug, debug);
debug.tracingModel = PROJECTIONMODEL_LINEAR;
debug.loopStartPositionSSX = uint(startPositionSS.x);
debug.loopStartPositionSSY = uint(startPositionSS.y);
debug.loopStartLinearDepth = 1 / startPositionSS.z;
debug.loopRayDirectionSS = raySS;
debug.loopIterationMax = iteration;
debug.iterationPositionSS = debugIterationPositionSS;
debug.iterationMipLevel = mipLevel;
debug.iteration = debugIteration;
debug.iterationLinearDepthBuffer = debugIterationLinearDepthBuffer;
debug.endHitSuccess = hitSuccessful;
debug.endLinearDepth = hit.linearDepth;
debug.endPositionSSX = hit.positionSS.x;
debug.endPositionSSY = hit.positionSS.y;
debug.iterationCellSizeW = 1 << mipLevel;
debug.iterationCellSizeH = 1 << mipLevel;
debug.tracingModel = PROJECTIONMODEL_LINEAR;
debug.loopStartPositionSSX = uint(startPositionSS.x);
debug.loopStartPositionSSY = uint(startPositionSS.y);
debug.loopStartLinearDepth = 1 / startPositionSS.z;
debug.loopRayDirectionSS = raySS;
debug.loopIterationMax = iteration;
debug.iterationPositionSS = debugIterationPositionSS;
debug.iterationMipLevel = mipLevel;
debug.iteration = debugIteration;
debug.iterationLinearDepthBufferMin = debugIterationLinearDepthBufferMin;
debug.iterationLinearDepthBufferMinThickness = debugIterationLinearDepthBufferMinThickness;
debug.iterationLinearDepthBufferMax = debugIterationLinearDepthBufferMax;
debug.endHitSuccess = hitSuccessful;
debug.endLinearDepth = hit.linearDepth;
debug.endPositionSSX = hit.positionSS.x;
debug.endPositionSSY = hit.positionSS.y;
debug.iterationCellSizeW = 1 << mipLevel;
debug.iterationCellSizeH = 1 << mipLevel;
_DebugScreenSpaceTracingData[0] = debug;
}

float3 debugIterationPositionSS = float3(0, 0, 0);
uint debugIteration = 0u;
uint debugIterationIntersectionKind = 0u;
float debugIterationLinearDepthBuffer = 0;
float debugIterationLinearDepthBufferMin = 0;
float debugIterationLinearDepthBufferMinThickness = 0;
float debugIterationLinearDepthBufferMax = 0;
#endif
iteration = 0u;

uint2 cellSize = uint2(1, 1) << currentLevel;
float3 positionSS = startPositionSS;
float invLinearDepth = 0;
float2 invLinearDepth = float2(0.0, 0.0);
while (currentLevel >= minMipLevel)
{

// Sampled as 1/Z so it interpolate properly in screen space.
invLinearDepth = LoadInvDepth(positionSS.xy, currentLevel);
float positionLinearDepth = 1 / positionSS.z;
float minLinearDepth = 1 / invLinearDepth.r;
float maxLinearDepth = minLinearDepth + settingsRayDepthSuccessBias;
bool isAboveDepth = positionLinearDepth <= minLinearDepth;
bool isAboveThickness = positionLinearDepth <= maxLinearDepth;
bool isBehindDepth = !isAboveThickness;
bool intersectWithDepth = minLinearDepth >= positionLinearDepth && isAboveThickness;
if (IsPositionAboveDepth(positionSS.z, invLinearDepth))
// Nominal case, we raymarch in front of the depth buffer and accelerate with HiZ
if (isAboveDepth)
float3 candidatePositionSS = IntersectDepthPlane(positionSS, raySS, invLinearDepth);
float3 candidatePositionSS = IntersectDepthPlane(positionSS, raySS, invLinearDepth.r);
intersectionKind = HIZINTERSECTIONKIND_DEPTH;

positionSS = candidatePositionSS;
}
// Raymarching behind object in depth buffer, this case degenerate into a linear search
else if (isBehindDepth && currentLevel <= (minMipLevel + 1))
{
const int2 cellId = int2(positionSS.xy) / cellSize;
positionSS = IntersectCellPlanes(
positionSS,
raySS,
invRaySS,
cellId,
cellSize,
cellPlanes,
crossOffset
);
intersectionKind = HIZINTERSECTIONKIND_CELL;
mipLevelDelta = 1;
}
currentLevel = min(currentLevel + mipLevelDelta, maxMipLevel);

{
debugLoopMipMaxUsedLevel = max(debugLoopMipMaxUsedLevel, currentLevel);
debugIterationPositionSS = positionSS;
debugIterationLinearDepthBuffer = 1 / invLinearDepth;
debugIterationLinearDepthBufferMin = 1 / invLinearDepth.r;
debugIterationLinearDepthBufferMinThickness = 1 / invLinearDepth.r + settingsRayDepthSuccessBias;
debugIterationLinearDepthBufferMax = 1 / invLinearDepth.g;
debugIteration = iteration;
debugIterationIntersectionKind = intersectionKind;
debugIterationCellSize = cellSize;

ScreenSpaceTracingDebug debug;
ZERO_INITIALIZE(ScreenSpaceTracingDebug, debug);
debug.tracingModel = PROJECTIONMODEL_HI_Z;
debug.loopStartPositionSSX = uint(startPositionSS.x);
debug.loopStartPositionSSY = uint(startPositionSS.y);
debug.loopStartLinearDepth = 1 / startPositionSS.z;
debug.loopRayDirectionSS = raySS;
debug.loopMipLevelMax = debugLoopMipMaxUsedLevel;
debug.loopIterationMax = iteration;
debug.iterationPositionSS = debugIterationPositionSS;
debug.iterationMipLevel = debugIterationMipLevel;
debug.iteration = debugIteration;
debug.iterationLinearDepthBuffer = debugIterationLinearDepthBuffer;
debug.iterationIntersectionKind = debugIterationIntersectionKind;
debug.iterationCellSizeW = debugIterationCellSize.x;
debug.iterationCellSizeH = debugIterationCellSize.y;
debug.endHitSuccess = hitSuccessful;
debug.endLinearDepth = hit.linearDepth;
debug.endPositionSSX = hit.positionSS.x;
debug.endPositionSSY = hit.positionSS.y;
debug.tracingModel = PROJECTIONMODEL_HI_Z;
debug.loopStartPositionSSX = uint(startPositionSS.x);
debug.loopStartPositionSSY = uint(startPositionSS.y);
debug.loopStartLinearDepth = 1 / startPositionSS.z;
debug.loopRayDirectionSS = raySS;
debug.loopMipLevelMax = debugLoopMipMaxUsedLevel;
debug.loopIterationMax = iteration;
debug.iterationPositionSS = debugIterationPositionSS;
debug.iterationMipLevel = debugIterationMipLevel;
debug.iteration = debugIteration;
debug.iterationLinearDepthBufferMin = debugIterationLinearDepthBufferMin;
debug.iterationLinearDepthBufferMinThickness = debugIterationLinearDepthBufferMinThickness;
debug.iterationLinearDepthBufferMax = debugIterationLinearDepthBufferMax;
debug.iterationIntersectionKind = debugIterationIntersectionKind;
debug.iterationCellSizeW = debugIterationCellSize.x;
debug.iterationCellSizeH = debugIterationCellSize.y;
debug.endHitSuccess = hitSuccessful;
debug.endLinearDepth = hit.linearDepth;
debug.endPositionSSX = hit.positionSS.x;
debug.endPositionSSY = hit.positionSS.y;
_DebugScreenSpaceTracingData[0] = debug;
}

out ScreenSpaceRayHit hit
)
{
#ifdef DEBUG_DISPLAY
int debuggedAlgorithm = int(SSRT_SETTING(DebuggedAlgorithm, SSRTID));
#else
int debuggedAlgorithm = int(PROJECTIONMODEL_NONE);
#endif
#if DEBUG_DISPLAY
int(SSRT_SETTING(DebuggedAlgorithm, SSRTID)),
#else
int(PROJECTIONMODEL_NONE),
#endif
debuggedAlgorithm,
// Out
hit
);

正在加载...
取消
保存