I am more interested by your implementation of HiTrace.
My implementation (majority of the code is based on the implementation of you guy, mix):
mainPS:
// Get Data
float4 normal = float4( NormalTexture.Sample( NormalTextureSamp, uv ).xyz, 1.f );
// Early discard: Remove the sky and surfaces without normals
if ( ( dot( normal, float3( 1.f, 1.f, 1.f ) ) ) <= 0.f )
return 0;
float4 color = ColorTextureTexture.Sample( ColorTextureSamp, uv );
float4 depth = float4( DepthTexture.Sample( DepthTextureSamp, uv ).xxx, 1.f );
float4 vis = float4( MaterialTexture.Sample( MaterialTextureSamp, uv ).xyz, 1.f );
float4 hiZ = float4( HiZDepthTexture.Sample( HiZDepthTextureSamp, uv ).xyz, 1.f );
// World Normal To ViewSpace Normal
float3 viewNormal = normalize( mul( NormalFromGNormal( normal.xyz ), ( float3x3 )ViewMatrix ) );
float usedDepth = depth.z; // ( min, max, depth )
// UV Space To Clip Space
float4 projPos = float4( UVToClipXY( uv.xy ), usedDepth, 1.0 );
// Clip Space to View Space
projPos = mul( projPos, InvProjectionMatrix );
float3 viewPos = projPos.xyz/projPos.w;
float3 viewDir = normalize( viewPos );
float3 viewReflect = normalize( reflect( viewDir, viewNormal ) );
// Clip Plane result
float4 screenReflectPos = mul( float4( viewPos + viewReflect, 1.0 ), ProjectionMatrix );
/*
if ( abs( screenReflectPos.w ) < 0.001f )
return 0;
*/
screenReflectPos.xyz /= screenReflectPos.w;
// Back to UV Space
screenReflectPos.xy = ClipXYToUV( screenReflectPos.xy );
float3 screenPos = float3( uv, usedDepth );
// Operation on UV Space
float3 screenReflect = normalize( screenReflectPos.xyz - screenPos );
if ( screenReflect.z < 0.f )
return 0.f;
float4 newUV = hiZTrace( screenPos, screenReflect );
if ( newUV.x < 0.f || newUV.y < 0.f || newUV.x > 1.f || newUV.y > 1.f )
return 0.f;
/*
float4 foundPos = float4( float2( -1.0, 1.0 ) + newUV.xy*float2( 2.0, -2.0 ), newUV.z, 1.0 );
foundPos = mul( foundPos, InvProjectionMatrix );
float3 viewFoundPos = foundPos.xyz/foundPos.w;
float4 foundPosD = float4( float2( -1.0, 1.0 ) + newUV.xy*float2( 2.0, -2.0 ), depth.x, 1.0 );
foundPosD = mul( foundPos, InvProjectionMatrix );
float3 viewFoundPosD = foundPosD.xyz/foundPosD.w;
*/
float4 reflectedColor = ColorTextureTexture.Sample( ColorTextureTextureSamp, newUV.xy );
return reflectedColor;
And my HiTrace implementation:
float3 intersectDepthPlane( float3 o, float3 d, float t )
{
return o + d*t;
}
float2 getCell(float2 ray, float2 cellCount)
{
return floor( ray*cellCount );
}
float3 intersectCellBoundary(float3 o, float3 d, float2 cellIndex, float2 cellCount, float2 crossStep, float2 crossOffset)
{
float2 index = cellIndex + crossStep;
index /= cellCount;
index += crossOffset;
float2 delta = index - o.xy;
delta /= d.xy;
float t = min( delta.x, delta.y );
return intersectDepthPlane( o, d, t );
}
float2 getCellCount(float level, float rootLevel)
{
float2 div = ( level == 0.0f ? 1.0f : exp2( level ) );
return floor( ViewportSize.xy/div );
}
float3 getMinimumDepthPlane( float2 ray, float level, float rootLevel )
{
[branch]
if ( level == 0 )
return DepthTexture.tex.SampleLevel( DepthTexture.samp, ray.xy, 0.f ).xxx;
else
return HiZDepthTexture.tex.SampleLevel( HiZDepthTexture.samp, ray.xy, level ).xyz;
}
bool crossedCellBoundary( float2 cellIdxOne, float2 cellIdxTwo )
{
return floor( cellIdxOne.x ) != floor( cellIdxTwo.x ) || floor( cellIdxOne.y ) != floor( cellIdxTwo.y );
}
float4 hiZTrace( float3 p, float3 v )
{
const float rootLevel = HIZ_MAX_LEVEL - 1.0f;
float level = HIZ_START_LEVEL;
uint iterations = 0u;
float3 d = v.xyz / v.z;
float2 crossStep = float2( d.x >= 0.f ? 1.0f : -1.0f, d.y >= 0.f ? 1.0f : -1.0f );
float2 crossOffset = float2( crossStep.xy*HIZ_CROSS_EPSILON.xy );
crossStep.xy = saturate( crossStep.xy );
float4 ray = float4( p.xyz, 0.f );
float3 o = intersectDepthPlane( p, d, -p.z );
float2 hiZSize = getCellCount( level, rootLevel );
float2 rayCell = getCell( ray.xy, hiZSize );
ray.xyz = intersectCellBoundary( o, d, rayCell.xy, hiZSize.xy, crossStep.xy, crossOffset.xy );
float cumul = 0.f;
[loop]
while ( level >= HIZ_START_LEVEL && iterations < MAX_ITERATIONS )
{
crossStep = float2( d.x >= 0.f ? 1.0f : -1.0f, d.y >= 0.f ? 1.0f : -1.0f );
crossOffset = float2( crossStep.xy*HIZ_CROSS_EPSILON.xy );
crossStep.xy = saturate( crossStep.xy );
const float2 cellCount = getCellCount( level, rootLevel );
const float2 oldCellIdx = getCell( ray.xy, cellCount );
float3 zMinMax0 = getMinimumDepthPlane( ray.xy, level, rootLevel );
//float3 zMinMax1 = getMinimumDepthPlane( ray.xy, min( level + 1, HIZ_MAX_LEVEL ), rootLevel );
//float3 zClosest = min( zMinMax0, zMinMax1 );
float3 zClosest = zMinMax0;
float3 tmpRay = intersectDepthPlane( o, d, max( ray.z, zClosest.z ) );
// get the new cell number as well
const float2 newCellIdx = getCell( tmpRay.xy, cellCount );
[branch]
if ( crossedCellBoundary( oldCellIdx, newCellIdx ) )
{
tmpRay = intersectCellBoundary( o, d, oldCellIdx, cellCount.xy, crossStep.xy, crossOffset.xy );
level = min( HIZ_MAX_LEVEL, level + 1.f );
}
else
{
level = max( level - 1.f, 0 );
}
ray.xyz = tmpRay.xyz;
++iterations;
}
return float4( ray.xyz, iterations );
}
I try with power of 2 back Buffer but I still have noise or stairs depend of steps...
If you see something wrong on my code I will be happy :)
I am still working on "RayTracing" without blurring...
Thanks