Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HDRP][Path Tracing] Replaced recursive continuation rays with loop in ray generation #7090

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
b1ed6a4
Moved path tracing forward integrator to its own file.
eturquin Jan 25, 2022
e3f7aa8
Moved files for better consistency.
eturquin Jan 25, 2022
19fb5d9
Ray generation refactor.
eturquin Jan 25, 2022
5911aac
WIP
eturquin Jan 26, 2022
75bfb46
WIP
eturquin Feb 1, 2022
7ea3411
WIP
eturquin Feb 3, 2022
ffcb7c2
Mult by throughput on misses.
eturquin Feb 6, 2022
ffaf44d
WIP
eturquin Feb 6, 2022
9d3ae2a
WIP
eturquin Feb 7, 2022
a4dc385
Reached mostly functional state (still needs to reactivate volumes).
eturquin Feb 7, 2022
a067e31
Moved intensity clamping to raygen.
eturquin Feb 8, 2022
66dbf21
Reproduced former clamping scheme.
eturquin Feb 8, 2022
34f5d37
Removed sensor files.
eturquin Feb 8, 2022
708871e
More comments on Segment ID.
eturquin Feb 8, 2022
a6d81eb
Cleaned up PathIntersection aliasing.
eturquin Feb 8, 2022
86f2d83
Reactivated unlit shadow matte.
eturquin Feb 8, 2022
d216264
Added support for transparent Unlit continuation ray.
eturquin Feb 8, 2022
554d5ed
Adding volumes back (WIP)
eturquin Feb 8, 2022
49260fb
Fixed volume absorption and scattering.
eturquin Feb 8, 2022
f576a88
Minor code refactor for fog absorption.
eturquin Feb 8, 2022
5b956b0
Replaced *intersection variable names with payload.
eturquin Feb 8, 2022
7cc5149
Renamed PathIntersection to PathPayload.
eturquin Feb 8, 2022
5a7a244
Fixed bug with continuation rays hitting transparent surfaces.
eturquin Feb 8, 2022
bbb7375
Rework of the Miss system, support for non-sampled skies.
eturquin Feb 9, 2022
a8176bc
Simplified clamping.
eturquin Feb 9, 2022
f204ac8
Fixed fog absorption on sky values.
eturquin Feb 9, 2022
37c742a
Trying more aggressive clamping (will need to be further tested).
eturquin Feb 9, 2022
8be7544
Fixed with continuation ray init.
eturquin Feb 10, 2022
5f383b0
Removed clamping on throughput (was too strong).
eturquin Feb 10, 2022
ed20eb8
Merge branch 'master' into hd/pt_no_recursion
eturquin Feb 10, 2022
1e64195
...
eturquin Feb 10, 2022
8bd1493
Reached working state (still things to be double-checked)
eturquin Feb 10, 2022
c60a32c
Fixed issue with segmentID aliasing.
eturquin Feb 10, 2022
a11d407
Get AOV data straight form BSDF data.
eturquin Feb 10, 2022
13f692f
Fixed motion vector computation in AOV of the same name.
eturquin Feb 11, 2022
4a6772f
Merge branch 'master' into hd/pt_no_recursion
eturquin Feb 11, 2022
9b4c94a
Updated changelog.
eturquin Feb 11, 2022
95656d0
Updated reference images.
eturquin Feb 11, 2022
9564749
Merge branch 'master' into hd/pt_no_recursion
eturquin Feb 21, 2022
c638223
remove RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH Flag
remi-chapelain Feb 21, 2022
ff4d00b
Cleaned up corner cases with bad init and payload aliasing.
eturquin Feb 21, 2022
c4eda27
Set right payload instance for shadow computation on volumetric
eturquin Feb 22, 2022
770f28c
Simplified anyhit().
eturquin Feb 22, 2022
5fa4107
Skip closestHit as much as possible.
eturquin Feb 22, 2022
7ffbe6c
Cosmetic.
eturquin Feb 22, 2022
82e3d8e
Added roughness-based intensity clamp.
eturquin Feb 23, 2022
0cf403c
Reverted to previous clamping method.
eturquin Feb 23, 2022
13a42df
Merge branch 'master' into hd/pt_no_recursion
eturquin Feb 23, 2022
5a6e362
Merge branch 'master' into hd/pt_no_recursion
eturquin Feb 28, 2022
5cb5a89
Merge branch 'master' into hd/pt_no_recursion
eturquin Mar 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Reached working state (still things to be double-checked)
  • Loading branch information
eturquin committed Feb 10, 2022
commit 8bd1493ca8791f5346645d30eb85d073cc185141
Original file line number Diff line number Diff line change
Expand Up @@ -570,10 +570,7 @@ void RenderPathTracingFrame(RenderGraph renderGraph, HDCamera hdCamera, in Camer
}

// Run the computation
ctx.cmd.DispatchRays(data.shader, "TracePath", (uint)data.width, (uint)data.height, 1);

// FIXME AOV SUPPORT
//ctx.cmd.DispatchRays(data.shader, data.enableAOVs ? "RayGenAOV" : "RayGen", (uint)data.width, (uint)data.height, 1);
ctx.cmd.DispatchRays(data.shader, data.enableAOVs ? "RayGenAOV" : "RayGen", (uint)data.width, (uint)data.height, 1);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,65 +1,28 @@
#ifndef UNITY_PATH_TRACING_AOV_INCLUDED
#define UNITY_PATH_TRACING_AOV_INCLUDED

#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingIntersection.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingPayload.hlsl"

struct AOVData
{
float3 albedo;
float3 normal;
};

// Helper functions to read and write AOV values in the payload, hijacking other existing member variables
void SetAlbedo(inout PathIntersection payload, float3 albedo)
void WriteAOVData(AOVData aovData, float3 positionWS, inout PathPayload payload)
{
payload.cone.width = albedo.x;
payload.cone.spreadAngle = albedo.y;
payload.remainingDepth = asint(albedo.z);
}

float3 GetAlbedo(in PathIntersection payload)
{
return float3(payload.cone.width, payload.cone.spreadAngle, asfloat(payload.remainingDepth));
}

void SetNormal(inout PathIntersection payload, float3 normal)
{
payload.pixelCoord.x = asint(normal.x);
payload.pixelCoord.y = asint(normal.y);
payload.maxRoughness = normal.z;
}

float3 GetNormal(inout PathIntersection payload)
{
return float3(asfloat(payload.pixelCoord.x), asfloat(payload.pixelCoord.y), payload.maxRoughness);
}

void ClearAOVData(inout PathIntersection payload)
{
SetAlbedo(payload, 0.0);
SetNormal(payload, 0.0);
payload.motionVector = 0;
}

void WriteAOVData(inout PathIntersection pathIntersection, AOVData aovData, float3 positionWS)
{
SetAlbedo(pathIntersection, aovData.albedo);
SetNormal(pathIntersection, aovData.normal);

float2 jitteredPixelCoord = pathIntersection.motionVector;

// Compute motion vector
// Compute motion vector (from pixel coordinates and world position passed as inputs)
float3 prevPosWS = mul(unity_MatrixPreviousM, float4(positionWS, 1.0)).xyz;
float4 prevClipPos = mul(UNITY_MATRIX_PREV_VP, prevPosWS);
prevClipPos.xy /= prevClipPos.w;
prevClipPos.y = -prevClipPos.y;

float2 viewportSize = _ScreenSize.xy *_RTHandleScale.xy;
float2 prevFramePos = (prevClipPos.xy * 0.5 + 0.5) * viewportSize;
if (prevFramePos.x > 0 && prevFramePos.y > 0 && prevFramePos.x < viewportSize.x && prevFramePos.y < viewportSize.y)
pathIntersection.motionVector = prevFramePos - jitteredPixelCoord;
else
pathIntersection.motionVector = 0;
float2 prevPixelCoord = (prevClipPos.xy * 0.5 + 0.5) * viewportSize;

// Write final AOV values to the payload
payload.aovMotionVector = prevPixelCoord - payload.aovMotionVector;
payload.aovAlbedo = aovData.albedo;
payload.aovNormal = aovData.normal;
}

#endif //UNITY_PATH_TRACING_AOV_INCLUDED
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// Path tracing includes
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingPayload.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingAOV.hlsl"
#ifdef HAS_LIGHTLOOP
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingLight.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl"
Expand Down Expand Up @@ -123,6 +124,12 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
// Check if we want to compute direct and emissive lighting for current depth
bool computeDirect = payload.segmentID >= _RaytracingMinRecursion - 1;

// Get our world space shading position
float3 shadingPosition = fragInput.positionRWS;

// We will write our AOV data in there
AOVData aovData;

#ifndef SHADER_UNLIT

// Compute the bsdf data
Expand All @@ -132,9 +139,6 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
// Also make sure that it is in the same hemisphere as the shading normal (which may have been flipped)
bsdfData.geomNormalWS = dot(bsdfData.normalWS, geomNormal) > 0.0 ? geomNormal : -geomNormal;

// Get our world space shading position
float3 shadingPosition = fragInput.positionRWS;

// And reset the payload value, which will store our final radiance result for this path depth
payload.value = computeDirect ? builtinData.emissiveColor : 0.0;

Expand Down Expand Up @@ -258,6 +262,9 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
}
}

// Grab AOV data
GetAOVData(mtlData, aovData);

#else // SHADER_UNLIT

if (computeDirect)
Expand All @@ -272,6 +279,9 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
#endif
}

// Get the closest thing we have to a shading normal in the Unlit model
float3 shadingNormal = fragInput.tangentToWorld[2];

#ifdef _SURFACE_TYPE_TRANSPARENT
if (builtinData.opacity < 1.0)
{
Expand All @@ -280,10 +290,10 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
shadowPayload.segmentID = SEGMENT_ID_NEAREST_HIT;
shadowPayload.rayTHit = FLT_INF;

float bias = dot(WorldRayDirection(), fragInput.tangentToWorld[2]) > 0.0 ? _RaytracingRayBias : -_RaytracingRayBias;
float bias = dot(WorldRayDirection(), shadingNormal) > 0.0 ? _RaytracingRayBias : -_RaytracingRayBias;

RayDesc ray;
ray.Origin = fragInput.positionRWS + bias * fragInput.tangentToWorld[2];
ray.Origin = shadingPosition + bias * shadingNormal;
ray.Direction = WorldRayDirection();
ray.TMin = 0.0;
ray.TMax = FLT_INF;
Expand Down Expand Up @@ -312,7 +322,15 @@ void ComputeSurfaceScattering(inout PathPayload payload : SV_RayPayload, Attribu
}
#endif

// Grab AOV data for Unlit
aovData.albedo = surfaceData.color;
aovData.normal = shadingNormal;

#endif // SHADER_UNLIT

// Write AOV data to the payload (if needed)
if (payload.segmentID == 0 && any(payload.aovMotionVector))
WriteAOVData(aovData, shadingPosition, payload);
}

// Generic function that handles one scattering event (a vertex along the full path), can be either:
Expand All @@ -324,7 +342,7 @@ void ClosestHit(inout PathPayload payload : SV_RayPayload, AttributeData attribu
// Always set the new t value
payload.rayTHit = RayTCurrent();

if (payload.segmentID == SEGMENT_ID_NEAREST_HIT)
if (payload.segmentID == SEGMENT_ID_NEAREST_HIT )
return;

bool computeDirect = payload.segmentID >= _RaytracingMinRecursion - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSkySampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingAOV.hlsl"

// Input(s)
float4x4 _PixelCoordToViewDirWS;
Expand All @@ -32,6 +33,11 @@ float4 _PathTracingTilingParameters; // xy: tile count, zw: current tile in
// Output(s)
RW_TEXTURE2D_X(float4, _FrameTexture);

// AOVs
RW_TEXTURE2D_X(float4, _AlbedoAOV);
RW_TEXTURE2D_X(float4, _NormalAOV);
RW_TEXTURE2D_X(float4, _MotionVectorAOV);

[shader("miss")]
void CameraMiss(inout PathPayload payload : SV_RayPayload)
{
Expand Down Expand Up @@ -79,6 +85,9 @@ void CameraMiss(inout PathPayload payload : SV_RayPayload)
// Reinject the environment value
payload.value += envValue;
}

// Override AOV motion vector information
payload.aovMotionVector = 0.0;
}

[shader("miss")]
Expand Down Expand Up @@ -108,7 +117,7 @@ void ApplyDepthOfField(uint2 pixelCoord, float dotDirection, inout float3 origin
direction = normalize(focusPoint - origin);
}

void GenerateCameraRay(uint2 pixelCoord, out PathPayload payload, out RayDesc ray)
void GenerateCameraRay(uint2 pixelCoord, out PathPayload payload, out RayDesc ray, bool withAOV = false)
{
// Get the current tile coordinates (for interleaved tiling) and update pixel coordinates accordingly
uint2 tileCount = uint2(_PathTracingTilingParameters.xy);
Expand All @@ -130,6 +139,11 @@ void GenerateCameraRay(uint2 pixelCoord, out PathPayload payload, out RayDesc ra
payload.cone.spreadAngle = _RaytracingPixelSpreadAngle / min(tileCount.x, tileCount.y);
payload.cone.width = 0.0;

// The motion vector AOV value will also serve as a on/off indicator for AOV computations
payload.aovMotionVector = withAOV ? jitteredPixelCoord.xy : 0.0;
payload.aovAlbedo = 0.0;
payload.aovNormal = 0.0;

// Generate the ray descriptor for this pixel
ray.TMin = _RaytracingCameraNearPlane;
ray.TMax = FLT_INF;
Expand Down Expand Up @@ -167,16 +181,12 @@ float3 ClampValue(float3 value, float maxIntensity = _RaytracingIntensityClamp)
return intensity > maxIntensity ? value * maxIntensity / intensity : value;
}

[shader("raygeneration")]
void TracePath()
void TracePath(uint2 pixelCoord, bool withAOV = false)
{
// Get the current integer pixel coordinates
uint2 pixelCoord = DispatchRaysIndex().xy;

// Generate the camera segment of our path
PathPayload payload;
RayDesc ray;
GenerateCameraRay(pixelCoord, payload, ray);
GenerateCameraRay(pixelCoord, payload, ray, withAOV);

// Trace our camera ray
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_PATH_TRACING, 0, 1, 0, ray, payload);
Expand Down Expand Up @@ -204,7 +214,7 @@ void TracePath()
payload.value = 0.0;
payload.rayDirection = 0.0;
payload.pixelCoord = pixelCoord;
payload.segmentID = segmentID;
payload.segmentID = segmentID;

// Trace our continuation ray
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH,
Expand All @@ -222,4 +232,24 @@ void TracePath()

// Copy the full path radiance value (and alpha/presence) to our output buffer
_FrameTexture[COORD_TEXTURE2D_X(pixelCoord)] = float4(value, alpha);

if (withAOV)
{
// If we computed AOVs, copy relevant values to our output buffers
_AlbedoAOV[COORD_TEXTURE2D_X(pixelCoord)] = float4(payload.aovAlbedo, 1.0);
_NormalAOV[COORD_TEXTURE2D_X(pixelCoord)] = float4(payload.aovNormal, 1.0);
_MotionVectorAOV[COORD_TEXTURE2D_X(pixelCoord)] = float4(payload.aovMotionVector, 0.0, 1.0);
}
}

[shader("raygeneration")]
void RayGen()
{
TracePath(DispatchRaysIndex().xy);
}

[shader("raygeneration")]
void RayGenAOV()
{
TracePath(DispatchRaysIndex().xy, true);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,33 @@ struct PathPayload
//
// Input
//
uint2 pixelCoord; // Pixel coordinates from which the path emanates
uint segmentID; // Identifier for path segment (see above)
uint2 pixelCoord; // Pixel coordinates from which the path emanates
uint segmentID; // Identifier for path segment (see above)

//
// Input/output
//
float3 throughput; // Current path throughput
float maxRoughness; // Current maximum roughness encountered along the path
RayCone cone; // Ray differential information (not used currently)
float3 throughput; // Current path throughput
float maxRoughness; // Current maximum roughness encountered along the path
RayCone cone; // Ray differential information (not used currently)

//
// Output
//
float3 value; // Main value (radiance, or normal for random walk)
float3 rayDirection; // Continuation ray direction, null means no continuation
float rayTHit; // Ray parameter, used either for current or next hit
float3 value; // Main value (radiance, or normal for random walk)
float3 rayDirection; // Continuation ray direction, null means no continuation
float rayTHit; // Ray parameter, used either for current or next hit

//
// AOV Input/output
//
float2 aovMotionVector; // Motion vector (also serve as on/off AOV switch)

//
// AOV Output
//
float3 aovAlbedo; // Diffuse reflectance
float3 aovNormal; // Shading normal
};

void SetContinuationRayOrigin(float3 origin, out PathPayload payload)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void ComputeVolumeScattering(inout PathPayload payload : SV_RayPayload, float3 i
{
if (SampleLights(lightList, inputSample, scatteringPosition, 0.0, true, ray.Direction, value, pdf, ray.TMax, shadowOpacity))
{
// FIXME: Apply phase function and divide by pdf (only isotropic for now, and not sure about sigmaS value)
// Apply phase function and divide by PDF
value *= _HeightFogBaseScattering.xyz * ComputeHeightFogMultiplier(scatteringPosition.y) * INV_FOUR_PI / pdf;

if (Luminance(value) > 0.001)
Expand All @@ -129,6 +129,8 @@ void ComputeVolumeScattering(inout PathPayload payload : SV_RayPayload, float3 i
}
}

// Override AOV motion vector information
payload.aovMotionVector = 0.0;
}

#endif // UNITY_PATH_TRACING_VOLUME_INCLUDED