Skip to content

Commit

Permalink
NRD updated to v4.10.0:
Browse files Browse the repository at this point in the history
- PT: fixed curvature (scaling from matrices was applied incorrectly)
- PT: curvature computed on the fly, using minimal per-primitive data, coming from the CPU side
- PT: simplified curvature usage for hit distance estimation for NRD (omitted some hacks)
- UI: added "boost" option, which is available if SHARC is ON (it's a good practice to shorten history by ~30% if SHARC is available)
- hooked new NRD integration features (FP16 promotion and FP32 demotion)
- NRI updated to v1.152
- code improvements
- updated tests
  • Loading branch information
dzhdanNV committed Oct 9, 2024
1 parent 003f56a commit 2573b8b
Show file tree
Hide file tree
Showing 20 changed files with 257 additions and 208 deletions.
14 changes: 13 additions & 1 deletion .args
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,19 @@
},
{
"Command": "--scene=Kitchen/Kitchen.gltf"
}
},
{
"Command": "--scene=Bistro2/bistro.gltf"
},
{
"Command": "--scene=LivingRoom/living_room.gltf"
},
{
"Command": "--scene=TransparentMachines/transparent-machines-pt1.gltf"
},
{
"Command": "--scene=CornellBox/cornellBox.gltf"
},
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion External/NRD
Submodule NRD updated from ebf92a to b68073
2 changes: 1 addition & 1 deletion External/NRIFramework
3 changes: 1 addition & 2 deletions Shaders/DlssAfter.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ void main( uint2 pixelPos : SV_DispatchThreadId )

float3 color = gOut_Image[ pixelPos ];

bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR );
color = ApplyTonemap( color );
if( isSrgb )
if( gIsSrgb )
color = Color::ToSrgb( saturate( color ) );

// Output
Expand Down
5 changes: 2 additions & 3 deletions Shaders/Final.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ void main( uint2 pixelPos : SV_DispatchThreadId )
// Noisy input
float3 input = gIn_PreAA.SampleLevel( gNearestSampler, pixelUv * gRectSize * gInvRenderSize, 0 ).xyz;

bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR );
input = ApplyTonemap( input );
if( isSrgb )
if( gIsSrgb )
input = Color::ToSrgb( saturate( input ) );

// Split screen - noisy input / denoised output
Expand All @@ -43,7 +42,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId )
Rng::Hash::Initialize( pixelPos, gFrameIndex );

float rnd = Rng::Hash::GetFloat( );
result += ( rnd - 0.5 ) / ( isSrgb ? 256.0 : 1024.0 );
result += ( rnd - 0.5 ) / ( gIsSrgb ? 256.0 : 1024.0 );

// Split screen - vertical line
float verticalLine = saturate( 1.0 - abs( pixelUv.x - gSeparator ) * gWindowSize.x / 3.5 );
Expand Down
58 changes: 34 additions & 24 deletions Shaders/Include/RaytracingShared.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct GeometryProps
float3 N;
float2 uv;
float mip;
float tmin;
float hitT;
float curvature;
uint textureOffsetAndFlags;
uint instanceIndex;
Expand All @@ -53,7 +53,7 @@ struct GeometryProps
{ return ( ( textureOffsetAndFlags >> 2 ) & 0x1 ) ? float3( 1.0, 0.0, 0.0 ) : float3( 0.0, 1.0, 0.0 ); }

bool IsSky( )
{ return tmin == INF; }
{ return hitT == INF; }
};

float2 GetConeAngleFromAngularRadius( float mip, float tanConeAngle )
Expand Down Expand Up @@ -118,12 +118,14 @@ float3 GetSamplingCoords( uint textureIndex, float2 uv, float mip, int mode )
if( instanceData.textureOffsetAndFlags & ( FLAG_STATIC << FLAG_FIRST_BIT ) ) \
mObjectToWorld = ( float3x3 )mOverloaded; \
\
float flip = Math::Sign( instanceData.invScale ) * ( rayQuery.CandidateTriangleFrontFace( ) ? -1.0 : 1.0 ); \
float flip = Math::Sign( instanceData.scale ) * ( rayQuery.CandidateTriangleFrontFace( ) ? -1.0 : 1.0 ); \
\
/* Primitive */ \
uint primitiveIndex = instanceData.primitiveOffset + rayQuery.CandidatePrimitiveIndex( ); \
PrimitiveData primitiveData = gIn_PrimitiveData[ primitiveIndex ]; \
\
float worldArea = primitiveData.worldArea * instanceData.scale * instanceData.scale; \
\
/* Barycentrics */ \
float3 barycentrics; \
barycentrics.yz = rayQuery.CandidateTriangleBarycentrics( ); \
Expand All @@ -141,12 +143,12 @@ float3 GetSamplingCoords( uint textureIndex, float2 uv, float mip, int mode )
N = Geometry::RotateVector( mObjectToWorld, N ); \
N = normalize( N * flip ); \
\
/* Mip level ( TODO: doesn't take into account integrated AO / SO - i.e. diffuse = lowest mip, but what if we see the sky through a tiny hole? ) */ \
float NoR = abs( dot( rayQuery.WorldRayDirection( ), N ) ); \
/* Mip level */ \
float NoRay = abs( dot( rayQuery.WorldRayDirection( ), N ) ); \
float a = rayQuery.CandidateTriangleRayT( ); \
a *= mipAndCone.y; \
a *= Math::PositiveRcp( NoR ); \
a *= primitiveData.worldToUvUnits * abs( instanceData.invScale ); \
a *= Math::PositiveRcp( NoRay ); \
a *= sqrt( primitiveData.uvArea / worldArea ); \
\
float mip = log2( a ); \
mip += MAX_MIP_LEVEL; \
Expand Down Expand Up @@ -210,19 +212,19 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax,
while( rayQuery.Proceed( ) )
CheckNonOpaqueTriangle( rayQuery, mipAndCone );

// TODO: reuse data if committed == candidate (use T to check)
// TODO: reuse data if committed == candidate ( use T to check )
GeometryProps props = ( GeometryProps )0;
props.mip = mipAndCone.x;

if( rayQuery.CommittedStatus( ) == COMMITTED_NOTHING )
{
props.tmin = INF;
props.X = origin + direction * props.tmin;
props.hitT = INF;
props.X = origin + direction * props.hitT;
props.Xprev = props.X;
}
else
{
props.tmin = rayQuery.CommittedRayT( );
props.hitT = rayQuery.CommittedRayT( );

// Instance
uint instanceIndex = rayQuery.CommittedInstanceID( ) + rayQuery.CommittedGeometryIndex( );
Expand All @@ -240,12 +242,14 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax,
if( props.Has( FLAG_STATIC ) )
mObjectToWorld = ( float3x3 )mOverloaded;

float flip = Math::Sign( instanceData.invScale ) * ( rayQuery.CommittedTriangleFrontFace( ) ? -1.0 : 1.0 );
float flip = Math::Sign( instanceData.scale ) * ( rayQuery.CommittedTriangleFrontFace( ) ? -1.0 : 1.0 );

// Primitive
uint primitiveIndex = instanceData.primitiveOffset + rayQuery.CommittedPrimitiveIndex( );
PrimitiveData primitiveData = gIn_PrimitiveData[ primitiveIndex ];

float worldArea = primitiveData.worldArea * instanceData.scale * instanceData.scale;

// Barycentrics
float3 barycentrics;
barycentrics.yz = rayQuery.CommittedTriangleBarycentrics( );
Expand All @@ -262,14 +266,17 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax,
props.N = -N; // TODO: why negated?

// Curvature
props.curvature = barycentrics.x * primitiveData.curvature0_curvature1.x + barycentrics.y * primitiveData.curvature0_curvature1.y + barycentrics.z * primitiveData.curvature2_bitangentSign.x;
props.curvature /= abs( instanceData.invScale );

// Mip level (TODO: doesn't take into account integrated AO / SO - i.e. diffuse = lowest mip, but what if we see the sky through a tiny hole?)
float NoR = abs( dot( direction, props.N ) );
float a = props.tmin * mipAndCone.y;
a *= Math::PositiveRcp( NoR );
a *= primitiveData.worldToUvUnits * abs( instanceData.invScale );
float dnSq0 = Math::LengthSquared( n0 - n1 );
float dnSq1 = Math::LengthSquared( n1 - n2 );
float dnSq2 = Math::LengthSquared( n2 - n0 );
float dnSq = max( dnSq0, max( dnSq1, dnSq2 ) );
props.curvature = sqrt( dnSq / worldArea );

// Mip level
float NoRay = abs( dot( direction, props.N ) );
float a = props.hitT * mipAndCone.y;
a *= Math::PositiveRcp( NoRay );
a *= sqrt( primitiveData.uvArea / worldArea );

float mip = log2( a );
mip += MAX_MIP_LEVEL;
Expand All @@ -287,9 +294,9 @@ GeometryProps CastRay( float3 origin, float3 direction, float Tmin, float Tmax,
float3 T = barycentrics.x * t0 + barycentrics.y * t1 + barycentrics.z * t2;
T = Geometry::RotateVector( mObjectToWorld, T );
T = normalize( T );
props.T = float4( T, primitiveData.curvature2_bitangentSign.y );
props.T = float4( T, primitiveData.bitangentSign_unused.x );

props.X = origin + direction * props.tmin;
props.X = origin + direction * props.hitT;
if( props.Has( FLAG_DEFORMABLE ) )
{
MorphedPrimitivePrevPositions prev = gIn_MorphedPrimitivePrevPositions[ instanceData.morphedPrimitiveOffset + rayQuery.CommittedPrimitiveIndex( ) ];
Expand Down Expand Up @@ -361,7 +368,10 @@ MaterialProps GetMaterialProps( GeometryProps geometryProps, bool viewIndependen
float3 T = geometryProps.T.xyz;

// Estimate curvature
float curvature = length( Geometry::UnpackLocalNormal( packedNormal ).xy ) * float( gUseNormalMap );
float viewZ = Geometry::AffineTransform( gWorldToView, geometryProps.X ).z;
float pixelSize = gUnproject * lerp( abs( viewZ ), 1.0, abs( gOrthoMode ) );
float localCurvature = length( Geometry::UnpackLocalNormal( packedNormal ).xy ) * float( gUseNormalMap );
localCurvature /= pixelSize;

// Emission
coords = GetSamplingCoords( baseTexture + 3, geometryProps.uv, geometryProps.mip, MIP_VISIBILITY );
Expand Down Expand Up @@ -501,7 +511,7 @@ MaterialProps GetMaterialProps( GeometryProps geometryProps, bool viewIndependen
props.baseColor = baseColor;
props.roughness = roughness;
props.metalness = metalness;
props.curvature = geometryProps.curvature + curvature;
props.curvature = geometryProps.curvature + localCurvature;

return props;
}
Expand Down
13 changes: 9 additions & 4 deletions Shaders/Include/Shared.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ struct PrimitiveData
float16_t2 t1;

float16_t2 t2;
float16_t2 curvature0_curvature1;
float16_t2 curvature2_bitangentSign;
float worldToUvUnits;
float16_t2 bitangentSign_unused;
float worldArea;
float uvArea;
};

struct InstanceData
Expand All @@ -223,7 +223,7 @@ struct InstanceData

// TODO: handling object scale embedded into the transformation matrix (assuming uniform scale)
// TODO: sign represents triangle winding
float invScale;
float scale;
};

//===============================================================
Expand Down Expand Up @@ -385,6 +385,11 @@ float GetSpecMagicCurve( float roughness )
return f;
}

float ApplyThinLensEquation( float hitDist, float curvature )
{
return hitDist / ( 2.0 * curvature * hitDist + 1.0 );
}

// Returns 3D motion in world space or 2.5D motion in screen space
float3 GetMotion( float3 X, float3 Xprev )
{
Expand Down
14 changes: 11 additions & 3 deletions Shaders/SharcUpdate.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ float3 GetAmbientBRDF( GeometryProps geometryProps, MaterialProps materialProps,
[numthreads( 16, 16, 1 )]
void main( uint2 pixelPos : SV_DispatchThreadId )
{
/*
TODO: modify SHARC to support:
- material de-modulation
- 2 levels of detail: fine and coarse ( large voxels )
- firefly suppression
- anti-lag
- dynamic "sceneScale"
- auto "sceneScale" adjustment to guarantee desired number of samples in voxels on average
*/

// Initialize RNG
Rng::Hash::Initialize( pixelPos, gFrameIndex );

Expand Down Expand Up @@ -86,8 +96,7 @@ void main( uint2 pixelPos : SV_DispatchThreadId )
sharcHitData.normalWorld = normalize( geometryProps.N + ( Rng::Hash::GetFloat4( ).xyz - 0.5 ) * SHARC_NORMAL_DITHER );

SharcSetThroughput( sharcState, 1.0 );

if( !SharcUpdateHit( sharcState, sharcHitData, L, Rng::Hash::GetFloat( ) ) )
if( !SharcUpdateHit( sharcState, sharcHitData, L, 1.0 ) )
return;
}

Expand Down Expand Up @@ -246,7 +255,6 @@ void main( uint2 pixelPos : SV_DispatchThreadId )
sharcHitData.normalWorld = normalize( geometryProps.N + ( Rng::Hash::GetFloat4( ).xyz - 0.5 ) * SHARC_NORMAL_DITHER );

SharcSetThroughput( sharcState, throughput );

if( geometryProps.IsSky( ) )
SharcUpdateMiss( sharcState, L );
else if( !SharcUpdateHit( sharcState, sharcHitData, L, Rng::Hash::GetFloat( ) ) )
Expand Down
5 changes: 2 additions & 3 deletions Shaders/Taa.cs.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ void main( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SV_DispatchThreadI
history.xyz = max( history.xyz, 0.0 ); // yes, not "saturate"

// Remove transfer
bool isSrgb = gIsSrgb && ( gOnScreen == SHOW_FINAL || gOnScreen == SHOW_BASE_COLOR );
if( isSrgb )
if( gIsSrgb )
history.xyz = Color::FromSrgb( history.xyz );

// Update mix rate
Expand Down Expand Up @@ -160,7 +159,7 @@ void main( int2 threadPos : SV_GroupThreadId, int2 pixelPos : SV_DispatchThreadI
float3 result = lerp( clampedHistory, input, mixRate );

// Apply transfer
if( isSrgb )
if( gIsSrgb )
result = Color::ToSrgb( result );

// Output
Expand Down
Loading

0 comments on commit 2573b8b

Please sign in to comment.