diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 69b3a8bb1cd..e5ca027b561 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -763,6 +763,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Refactored shadow caching system. - Removed experimental namespace for ray tracing code. - Increase limit for max numbers of lights in UX +- Removed direct use of BSDFData in the path tracing pass, delegated to the material instead. ## [7.1.1] - 2019-09-05 diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitPathTracing.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitPathTracing.hlsl index 32358051f8f..b10668cf278 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitPathTracing.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitPathTracing.hlsl @@ -336,3 +336,34 @@ void EvaluateMaterial(MaterialData mtlData, float3 sampleDir, out MaterialResult #endif } } + +float AdjustPathRoughness(MaterialData mtlData, MaterialResult mtlResult, bool isSampleBelow, float pathRoughness) +{ + // Adjust the max roughness, based on the estimated diff/spec ratio + float adjustedPathRoughness = (mtlResult.specPdf * max(mtlData.bsdfData.roughnessT, mtlData.bsdfData.roughnessB) + mtlResult.diffPdf) / (mtlResult.diffPdf + mtlResult.specPdf); + +#ifdef _SURFACE_TYPE_TRANSPARENT + // When transmitting with an IOR close to 1.0, roughness is barely noticeable -> take that into account for path roughness adjustment + if (IsBelow(mtlData) != isSampleBelow) + adjustedPathRoughness = lerp(pathRoughness, adjustedPathRoughness, smoothstep(1.0, 1.3, mtlData.bsdfData.ior)); +#endif + + return adjustedPathRoughness; +} + +float3 ApplyAbsorption(MaterialData mtlData, float dist, bool isSampleBelow, float3 value) +{ +#if defined(_SURFACE_TYPE_TRANSPARENT) && HAS_REFRACTION + // Apply absorption on rays below the interface, using Beer-Lambert's law + if (isSampleBelow) + { + #ifdef _REFRACTION_THIN + value *= exp(-mtlData.bsdfData.absorptionCoefficient * REFRACTION_THIN_DISTANCE); + #else + value *= exp(-mtlData.bsdfData.absorptionCoefficient * dist); + #endif + } +#endif + + return value; +} diff --git a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl index 46bbb8e3cee..4520bc70bc2 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassPathTracing.hlsl @@ -176,18 +176,12 @@ void ClosestHit(inout PathIntersection pathIntersection : SV_RayPayload, Attribu nextPathIntersection.remainingDepth = pathIntersection.remainingDepth - 1; nextPathIntersection.t = rayDescriptor.TMax; - // Adjust the max roughness, based on the estimated diff/spec ratio - nextPathIntersection.maxRoughness = (mtlResult.specPdf * max(mtlData.bsdfData.roughnessT, mtlData.bsdfData.roughnessB) + mtlResult.diffPdf) / pdf; + // Adjust the path max roughness (used for roughness clamping, to reduce fireflies) + nextPathIntersection.maxRoughness = AdjustPathRoughness(mtlData, mtlResult, isSampleBelow, pathIntersection.maxRoughness); // In order to achieve filtering for the textures, we need to compute the spread angle of the pixel nextPathIntersection.cone.spreadAngle = pathIntersection.cone.spreadAngle + roughnessToSpreadAngle(nextPathIntersection.maxRoughness); -#ifdef _SURFACE_TYPE_TRANSPARENT - // When transmitting with an IOR close to 1.0, roughness is barely noticeable -> take that into account for roughness clamping - if (IsBelow(mtlData) != isSampleBelow) - nextPathIntersection.maxRoughness = lerp(pathIntersection.maxRoughness, nextPathIntersection.maxRoughness, smoothstep(1.0, 1.3, mtlData.bsdfData.ior)); -#endif - // Shoot ray for indirect lighting TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, RAYTRACINGRENDERERFLAG_PATH_TRACING, 0, 1, 2, rayDescriptor, nextPathIntersection); @@ -203,19 +197,9 @@ void ClosestHit(inout PathIntersection pathIntersection : SV_RayPayload, Attribu nextPathIntersection.value += lightValue * misWeight; } -#if defined(_SURFACE_TYPE_TRANSPARENT) && HAS_REFRACTION - // Apply absorption on rays below the interface, using Beer-Lambert's law - if (isSampleBelow) - { - #ifdef _REFRACTION_THIN - nextPathIntersection.value *= exp(-mtlData.bsdfData.absorptionCoefficient * REFRACTION_THIN_DISTANCE); - #else - // FIXME: maxDist might need some more tweaking - float maxDist = surfaceData.atDistance * 10.0; - nextPathIntersection.value *= exp(-mtlData.bsdfData.absorptionCoefficient * min(nextPathIntersection.t, maxDist)); - #endif - } -#endif + // Apply material absorption + float dist = min(nextPathIntersection.t, surfaceData.atDistance * 10.0); + nextPathIntersection.value = ApplyAbsorption(mtlData, dist, isSampleBelow, nextPathIntersection.value); pathIntersection.value += value * rrFactor * nextPathIntersection.value; }