From 2b376f5a80a93e1f06e627b0d51106438dd6635c Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 10:20:49 +0100 Subject: [PATCH 1/9] Replaced quadratic solver with version from initial vol. branch. --- .../ShaderLibrary/GeometricTools.hlsl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl index a99778b109e..f91bb1ddd50 100644 --- a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl +++ b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl @@ -27,17 +27,15 @@ float3x3 RotationFromAxisAngle(float3 A, float sinAngle, float cosAngle) // Solver //----------------------------------------------------------------------------- -// Solves the quadratic equation of the form: a*t^2 + b*t + c = 0. -// Returns 'false' if there are no real roots, 'true' otherwise. -// Numerically stable. -// Ref: Numerical Recipes in C++ (3rd Edition) bool SolveQuadraticEquation(float a, float b, float c, out float2 roots) { - float d = b * b - 4 * a * c; - float q = -0.5 * (b + CopySign(sqrt(d), b)); - roots = float2(c / q, q / a); + float det = Sq(b) - 4.0 * a * c; - return (d >= 0); + float sqrtDet = sqrt(det); + roots.x = (-b - sign(a) * sqrtDet) / (2.0 * a); + roots.y = (-b + sign(a) * sqrtDet) / (2.0 * a); + + return (det >= 0.0); } //----------------------------------------------------------------------------- From be95b34b221d4b1acff6cfc131530787b2e8599c Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 11:00:35 +0100 Subject: [PATCH 2/9] Detect modified light transforms when building RT accel structs. --- .../RenderPipeline/Raytracing/HDRaytracingManager.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingManager.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingManager.cs index f89ee75e2fa..1786510421d 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingManager.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/HDRaytracingManager.cs @@ -341,8 +341,10 @@ AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer, if (instanceFlag == 0) return AccelerationStructureStatus.Added; // Add it to the acceleration structure - m_TransformDirty |= currentRenderer.transform.hasChanged; m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); + + // Indicates that a transform has changed in our scene (mesh or light) + m_TransformDirty |= currentRenderer.transform.hasChanged; currentRenderer.transform.hasChanged = false; // return the status @@ -387,6 +389,10 @@ internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera) m_RayTracedShadowsRequired |= (hdLight.useRayTracedShadows && screenSpaceShadowsSupported); m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow); + // Indicates that a transform has changed in our scene (mesh or light) + m_TransformDirty |= hdLight.transform.hasChanged; + hdLight.transform.hasChanged = false; + switch (hdLight.type) { case HDLightType.Directional: From a0ab0a36778dc721a8bb5fbb1fdc412e80955e75 Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 11:03:37 +0100 Subject: [PATCH 3/9] Cosmetic. --- .../Runtime/RenderPipeline/PathTracing/PathTracing.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs index a9f817011a1..3d6238c4326 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/PathTracing.cs @@ -198,6 +198,13 @@ private void CheckDirtiness(HDCamera hdCamera) return; } + // Check light or geometry transforms dirtiness + if (m_TransformDirty) + { + m_TransformDirty = false; + ResetPathTracing(); + } + // Check lights dirtiness if (m_CacheLightCount != m_RayTracingLights.lightCount) { @@ -208,10 +215,9 @@ private void CheckDirtiness(HDCamera hdCamera) // Check geometry dirtiness ulong accelSize = m_CurrentRAS.GetSize(); - if (accelSize != m_CacheAccelSize || m_TransformDirty) + if (accelSize != m_CacheAccelSize) { m_CacheAccelSize = accelSize; - m_TransformDirty = false; ResetPathTracing(); } } From cf58b4b51dad1602886bc5167b3d77ec1bec8bf0 Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 12:15:33 +0100 Subject: [PATCH 4/9] Updated Changelog. --- com.unity.render-pipelines.high-definition/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 0bbc69a2ee2..36cffcc62a8 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - Fixed probe volumes debug views. +- Fixed issues with path-traced volumetric scattering (cases 1295222, 1295234). ### Changed - Removed the material pass probe volumes evaluation mode. From 5e83d4f8152af80bfe8d7b828a57c9cdb88ae0cd Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 12:38:28 +0100 Subject: [PATCH 5/9] Added comment. --- .../ShaderLibrary/GeometricTools.hlsl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl index f91bb1ddd50..fabd77ef04a 100644 --- a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl +++ b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl @@ -27,6 +27,9 @@ float3x3 RotationFromAxisAngle(float3 A, float sinAngle, float cosAngle) // Solver //----------------------------------------------------------------------------- +// Solves the quadratic equation of the form: a*t^2 + b*t + c = 0. +// Returns 'false' if there are no real roots, 'true' otherwise. +// Ensures that roots.x <= roots.y. bool SolveQuadraticEquation(float a, float b, float c, out float2 roots) { float det = Sq(b) - 4.0 * a * c; From 390dfcc0fc26aa44bdf8de634799839fefc351fc Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 27 Nov 2020 12:41:52 +0100 Subject: [PATCH 6/9] Removed unnecessary sort. --- .../ShaderLibrary/GeometricTools.hlsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl index fabd77ef04a..289cb6a92b1 100644 --- a/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl +++ b/com.unity.render-pipelines.core/ShaderLibrary/GeometricTools.hlsl @@ -160,8 +160,8 @@ bool IntersectRayCone(float3 rayOrigin, float3 rayDirection, // Check whether we have at least 1 root. bool hit = SolveQuadraticEquation(a, 2 * b, c, roots); - tEntr = min(roots.x, roots.y); - tExit = max(roots.x, roots.y); + tEntr = roots.x; + tExit = roots.y; float3 pEntr = o + tEntr * d; float3 pExit = o + tExit * d; From a51c2312f6d5d6d8d16b1ffa5278e8b7048e837d Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 4 Dec 2020 02:52:29 +0100 Subject: [PATCH 7/9] Modified with simple sampling variant. --- .../Shaders/PathTracingVolume.hlsl | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl index cdea387dec0..5e8fdadb3ca 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl @@ -53,12 +53,14 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo #endif // FIXME: not quite sure what the sigmaS, sigmaT values are supposed to be... - const float sigmaS = (t == FLT_MAX) ? 1.0 : sqrt(Luminance(_HeightFogBaseScattering.xyz)); + const bool hasSurface = t < FLT_MAX; + const float sigmaS = hasSurface ? sqrt(Luminance(_HeightFogBaseScattering.xyz)) : 1.0; const float sigmaT = _HeightFogBaseExtinction; - const float transmittanceMax = exp(-tMax * sigmaT); + const float transmittanceMax = max(exp(-tMax * sigmaT), 0.01); + const float transmittanceThreshold = hasSurface ? 1.0 - min(0.5, transmittanceMax) : 1.0; const float pdfNoVolA = 1.0 - sigmaS; - const float pdfNoVolB = sigmaS * transmittanceMax; + const float pdfNoVolB = sigmaS * (1.0 - transmittanceThreshold); const float pdfNoVol = pdfNoVolA + pdfNoVolB; pdfVol *= 1.0 - pdfNoVol; @@ -77,12 +79,11 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo // Re-scale the sample sample /= sigmaS; - // Evaluate the length to a potential volume scattering event - if (-log(1.0 - sample) / sigmaT >= tMax) + if (sample >= transmittanceThreshold) { // Re-scale the sample - sample -= 1.0 - transmittanceMax; - sample /= transmittanceMax; + sample -= transmittanceThreshold; + sample /= 1.0 - transmittanceThreshold; // Set the pdf pdf *= pdfNoVol; @@ -90,11 +91,11 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo return false; } + // Re-scale the sample + sample /= transmittanceThreshold; + if (sampleLocalLights) { - // Re-scale the sample - sample /= 1.0 - transmittanceMax; - // Linear sampling float deltaT = tMax - tMin; t = tMin + sample * deltaT; @@ -104,12 +105,8 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo } else { - // Let's (avoid very low transmittance, for robustness sake (minor bias) - if (transmittanceMax < 0.01) - sample = sample * 0.99 / (1.0 - transmittanceMax); - - // Log sampling - float transmittance = 1.0 - sample; + // Exponential sampling + float transmittance = transmittanceMax + sample * (1.0 - transmittanceMax); t = -log(transmittance) / sigmaT; // Set the pdf From 787c6ea729f2c46bc98e84962a96e3bd902341c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 4 Dec 2020 03:27:42 +0100 Subject: [PATCH 8/9] Updated changelog. --- com.unity.render-pipelines.high-definition/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index ba82d7fea65..da1b50952d9 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -18,7 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Removed the material pass probe volumes evaluation mode. - Volume parameter of type Cubemap can now accept Cubemap render textures and custom render textures. -- Replaced last package version checker in Wizard to a link on Package Manager +- Replaced last package version checker in Wizard to a link on Package Manager. +- Improved robustness of volumetric sampling in path tracing (case 1295187). ## [10.3.0] - 2020-12-01 From 9660090b3be92c10a56b632c92744552216e106a Mon Sep 17 00:00:00 2001 From: Emmanuel Turquin Date: Fri, 4 Dec 2020 13:07:09 +0100 Subject: [PATCH 9/9] Brought it further simplifications (removed test on sigmaS). --- .../Shaders/PathTracingVolume.hlsl | 45 ++++++------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl index 5e8fdadb3ca..3786095d11e 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl @@ -52,32 +52,10 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo tMax = tFog; #endif - // FIXME: not quite sure what the sigmaS, sigmaT values are supposed to be... - const bool hasSurface = t < FLT_MAX; - const float sigmaS = hasSurface ? sqrt(Luminance(_HeightFogBaseScattering.xyz)) : 1.0; + // FIXME: not quite sure what the sigmaT value is supposed to be... const float sigmaT = _HeightFogBaseExtinction; - const float transmittanceMax = max(exp(-tMax * sigmaT), 0.01); - const float transmittanceThreshold = hasSurface ? 1.0 - min(0.5, transmittanceMax) : 1.0; - - const float pdfNoVolA = 1.0 - sigmaS; - const float pdfNoVolB = sigmaS * (1.0 - transmittanceThreshold); - const float pdfNoVol = pdfNoVolA + pdfNoVolB; - pdfVol *= 1.0 - pdfNoVol; - - if (sample >= sigmaS) - { - // Re-scale the sample - sample -= sigmaS; - sample /= 1.0 - sigmaS; - - // Set the pdf - pdf *= pdfNoVol; - - return false; - } - - // Re-scale the sample - sample /= sigmaS; + const float transmittanceTMax = max(exp(-tMax * sigmaT), 0.01); + const float transmittanceThreshold = t < FLT_MAX ? 1.0 - min(0.5, transmittanceTMax) : 1.0; if (sample >= transmittanceThreshold) { @@ -85,8 +63,8 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo sample -= transmittanceThreshold; sample /= 1.0 - transmittanceThreshold; - // Set the pdf - pdf *= pdfNoVol; + // Adjust the pdf + pdf *= 1.0 - transmittanceThreshold; return false; } @@ -94,23 +72,26 @@ bool SampleVolumeScatteringPosition(inout float sample, inout float t, inout flo // Re-scale the sample sample /= transmittanceThreshold; + // Adjust the pdf + pdf *= pdfVol * transmittanceThreshold; + if (sampleLocalLights) { // Linear sampling float deltaT = tMax - tMin; t = tMin + sample * deltaT; - // Set the pdf - pdf *= pdfVol / deltaT; + // Adjust the pdf + pdf /= deltaT; } else { // Exponential sampling - float transmittance = transmittanceMax + sample * (1.0 - transmittanceMax); + float transmittance = transmittanceTMax + sample * (1.0 - transmittanceTMax); t = -log(transmittance) / sigmaT; - // Set the pdf - pdf *= pdfVol * sigmaT * transmittance; + // Adjust the pdf + pdf *= sigmaT * transmittance; } return true;