-
Notifications
You must be signed in to change notification settings - Fork 839
Improved Area Light Support for Hair #6157
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
Conversation
…sphere scattering.
…ipleScattering/HairMultipleScattering.hlsl
Hi! This comment will help you figure out which jobs to run before merging your PR. The suggestions are dynamic based on what files you have changed. HDRP Depending on the scope of your PR, you may need to run more jobs than what has been suggested. Please speak to your lead or a Graphics SDET (#devs-graphics-automation) if you are unsure. |
@@ -161,6 +161,9 @@ public struct BSDFData | |||
|
|||
public float perceptualRoughnessRadial; | |||
|
|||
// Normalization factor for area lights. | |||
public Vector3 distributionNormalizationFactor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this new term that area lights compute to normalize the distribution. This is necessary for energy conservation since we are moving the position of the light.
@@ -318,7 +327,7 @@ SHADOW_TYPE EvaluateShadow_Directional( LightLoopContext lightLoopContext, Posit | |||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/PunctualLightCommon.hlsl" | |||
|
|||
float4 EvaluateCookie_Punctual(LightLoopContext lightLoopContext, LightData light, | |||
float3 lightToSample) | |||
float3 lightToSample, float lod = 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slight adjustment to punctual cookie sampling to take an optional mip level. MRP lights will take advantage of this to select the appropriate level (instead of defaulting to 0 like normal analytic lights).
shadow = min(shadow, NdotL > 0.0 ? GetContactShadow(lightLoopContext, light.contactShadowMask, light.isRayTracedContactShadow) : 1.0); | ||
{ | ||
// In certain cases (like hair) we allow to force the contact shadow sample. | ||
#ifdef LIGHT_EVALUATION_CONTACT_SHADOW_DISABLE_NDOTL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For non-shadow mapped lights we add this new light evaluation flag that allows hair to override the NdotL which cancels to contact shadow sample. This is important for Marschner since it's not exactly cosine weighted by NdotL due to the transmission lobe
com.unity.render-pipelines.high-definition/Runtime/Material/Hair/Hair.hlsl
Show resolved
Hide resolved
|
||
float3 L; | ||
|
||
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_HAIR_MARSCHNER)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MRP for Marschner
|
||
bsdfData.distributionNormalizationFactor = sqrt(alpha / alphaPrime); | ||
} | ||
else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Light Center + Solid Angle modulated roughness for Kajiya
@@ -1063,7 +1291,11 @@ DirectLighting EvaluateBSDF_Area(LightLoopContext lightLoopContext, | |||
} | |||
else | |||
{ | |||
#if 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add a toggle to the shader graph that allows a user to choose between the default LTC/GGX or improved method? Or just keep LTC always disabled for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is probably quite robust and strictly closer to reference in terms of actual shading but also overall brightness.
My only worry is with elongated and skewed area lights (one part of the elongated area light being much closer to the shaded surface) and with lights with cookies. These might result in brightness that's quite far off the reference, and be jarring if the hair is e.g. contrasting with forehead that's correctly lit with LTC. If in those cases GGX/LTC on hair gives a less incorrect result, I'd see that as the only reason to keep it as an option. But maybe it's sufficiently worse overall, that it wouldn't be a practical choice anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't afford both in the code for perf reasons anyway (vgpr). So totally fine with disabling LTC
@@ -22,7 +22,7 @@ void ProcessBSDFData(PathIntersection pathIntersection, BuiltinData builtinData, | |||
{ | |||
// NOTE: Currently we don't support ray-aligned ribbons in the acceleration structure, so our only H-calculation routines | |||
// are either stochastic or derived from a tube intersection. | |||
#if 1 | |||
#if 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decided to disable near field path traced model for now, just in case users provide hair geometry with bad strand normals- they will still get correct results for far field.
@@ -27,7 +27,7 @@ float DecodeHairStrandCount(float3 L, float4 strandCountProbe) | |||
HALF_SQRT_3_DIV_PI * L.x | |||
); | |||
|
|||
return abs(dot(strandCountProbe, Ylm)); | |||
return max(dot(strandCountProbe, Ylm), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixing a mistake I made with SH anti-ring.
...pelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl
Outdated
Show resolved
Hide resolved
com.unity.render-pipelines.high-definition/Runtime/Material/Hair/Hair.hlsl
Outdated
Show resolved
Hide resolved
com.unity.render-pipelines.high-definition/Runtime/Material/Hair/Hair.hlsl
Show resolved
Hide resolved
@@ -1063,7 +1291,11 @@ DirectLighting EvaluateBSDF_Area(LightLoopContext lightLoopContext, | |||
} | |||
else | |||
{ | |||
#if 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is probably quite robust and strictly closer to reference in terms of actual shading but also overall brightness.
My only worry is with elongated and skewed area lights (one part of the elongated area light being much closer to the shaded surface) and with lights with cookies. These might result in brightness that's quite far off the reference, and be jarring if the hair is e.g. contrasting with forehead that's correctly lit with LTC. If in those cases GGX/LTC on hair gives a less incorrect result, I'd see that as the only reason to keep it as an option. But maybe it's sufficiently worse overall, that it wouldn't be a practical choice anyway?
...pelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl
Outdated
Show resolved
Hide resolved
// Construct the most representative direction. | ||
// We must consider multiple specular lobes, on the backward (R, TRT) and forward (TT) scattering hemisphere. | ||
// For the backward hemisphere we handle R and TRT similarly, and use the MRP result (based on the "fake" normal just like how we use it for IBL). | ||
// For the forward hemisphere we need to approximate harsher. We can get away with falling back to the light center and modifying the roughness. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern here is that elongated lights with one end closer to the shaded point will appear too dark. I suppose I should try it out in action :)
What was the reasoning behind going with the solid-angle-based roughness tweak as opposed to MRP? Were the results worse with MRP?
com.unity.render-pipelines.high-definition/Runtime/Material/Hair/Hair.hlsl
Show resolved
Hide resolved
com.unity.render-pipelines.high-definition/Runtime/Material/Hair/Hair.hlsl
Show resolved
Hide resolved
…arily add back rect ref
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Run yamato, and add a comment on the removal of that division by PI :) ensure yamato is green!
...pelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl
Outdated
Show resolved
Hide resolved
…of the divide by PI
…tudinal distribution
Re-running Yamato. All of these failures seem like instabilities (including the smoke test one, still persisting after I merged master). I also provided QA a test project to validate this PR. |
Looks like we are 'green' test-wise, the failures are known instabilities. |
#endif | ||
|
||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightEvaluation.hlsl" | ||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/MaterialEvaluation.hlsl" | ||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/SurfaceShading.hlsl" | ||
|
||
float3 RayPlaneIntersect(in float3 rayOrigin, in float3 rayDirection, in float3 planeOrigin, in float3 planeNormal) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those set of function either alredy exist or should be moved into our geometry.hlsl common file
@qa: Merging to 22.1, the coverage by John is already great. |
* Initial commit MRP implementation * Barn door application * Add dominant marschner lobe direction skeleton * Finalize rect light MRP for marschner, handle forward + backward hemisphere scattering. * Force pathtracer to far-field in case users use geometry with bad normals. * com.unity.render-pipelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl * Fix SH ringing for multiple scattering * Add trivial support for cookies * Add Kajiya support for area light approximation (non-LTC) * remove Line area light MRP for now * Remove area rect reference * Update area light hair test scene and reference images * Select cookie mip based on solid angle, rename some functions, temporarily add back rect ref * Remove the useless div-by-1 and add a comment to explain the removal of the divide by PI * Add a comment to further explain the normalization we do on the longitudinal distribution * Remove the ref once again * Update test images for metal and vulkan * Add a zero-div guard to silence compiler warning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested thoroughly this on Windows platforms and found no visual issues both with strands and hair cards. ✔👍
* Initial commit MRP implementation * Barn door application * Add dominant marschner lobe direction skeleton * Finalize rect light MRP for marschner, handle forward + backward hemisphere scattering. * Force pathtracer to far-field in case users use geometry with bad normals. * com.unity.render-pipelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl * Fix SH ringing for multiple scattering * Add trivial support for cookies * Add Kajiya support for area light approximation (non-LTC) * remove Line area light MRP for now * Remove area rect reference * Update area light hair test scene and reference images * Select cookie mip based on solid angle, rename some functions, temporarily add back rect ref * Remove the useless div-by-1 and add a comment to explain the removal of the divide by PI * Add a comment to further explain the normalization we do on the longitudinal distribution * Remove the ref once again * Update test images for metal and vulkan * Add a zero-div guard to silence compiler warning
* Increasing HDRP fined pruned light tile count to 63. #5771 * Fix Upscaled Film Grain & Dither in HDRP (#6111) When using particular types of upscaling, (CAS, FSR, Catmull) the film grain quality produced by HDRP was lower than expected. This was caused by errors in the UV scale calculations for the grain texture. This change fixes the issue by modifying the scale calculations to use the final viewport size rather than the size of the current scaled/unscaled viewport. This works because film grain is always handled by "FinalPass" which always renders at final viewport size anyways. This change also fixes a few cases where the current resolution group would have been incorrect when CAS or FSR were being used as the upscaling method. * Update CHANGELOG.md * Fix regression that was introduced in a previous PR on the diffuse denoiser #6119 * Fix Light Loop Variant Warnings (1372256) #6135 * Bump the HDRP Template IET Framework Package Version #6134 * Update ray tracing and path tracing docs regarding custom interpolator limitations (#6126) * [HDRP] Disable DoF for orthographic cameras #6124 * update occlusion radius for directional light sample (#6154) Co-authored-by: Sean Puller <sean.puller@unity3d.com> * Clean up Public API Documentation #6151 * Fix Sky override not taken into account #6127 * [Fogbugz # 1372245] Hdrp/drs fixing pyramid blur #6136 * Improved Area Light Support for Hair (#6157) * Initial commit MRP implementation * Barn door application * Add dominant marschner lobe direction skeleton * Finalize rect light MRP for marschner, handle forward + backward hemisphere scattering. * Force pathtracer to far-field in case users use geometry with bad normals. * com.unity.render-pipelines.high-definition/Runtime/Material/Hair/MultipleScattering/HairMultipleScattering.hlsl * Fix SH ringing for multiple scattering * Add trivial support for cookies * Add Kajiya support for area light approximation (non-LTC) * remove Line area light MRP for now * Remove area rect reference * Update area light hair test scene and reference images * Select cookie mip based on solid angle, rename some functions, temporarily add back rect ref * Remove the useless div-by-1 and add a comment to explain the removal of the divide by PI * Add a comment to further explain the normalization we do on the longitudinal distribution * Remove the ref once again * Update test images for metal and vulkan * Add a zero-div guard to silence compiler warning * Update CHANGELOG.md * [HDRP][Path Tracing] Exposed 3 methods related to path tracing and accumulation. #6197 * [HDRP] Fix infitnite material import loop materials #6185 * fixed typo: users -> uses (#6162) * Don't blur if nothing to blur (saves memory due to RG) (#6183) * Fix local fog volumes z axis calculation #6068 * fixed passive voice (#6092) * Fixed grammar errors * fixed passive voice in decal doc * Update Decal.md * Update Decal.md * Update Decal.md * AxF Raytracing: fix performance mode distillation that was broken and removed in #9d6db83478c213bc066e5f728d94b7faa6662543 (#6104) * Add scale parameter in eye shader #6132 * updated Override Fog page (#6200) * updated fog override screenshot * changed Depth Extent to Volumetric Fog Distance * Fix missing pragma (#6204) * [HDRP] Fix custom pass motion vector texture access #6205 * Fix typo in MipBias tooltip in HDRenderPipelineUI.Skin (#6210) * Replace gizmos FindObjectsOfType with list registrations to avoid constant slowdown in large scenes. Merged editor guards blocks. (#6168) * [HDRP] Fix APV tooltip for Geometry Distance Offset (#6150) * Update tooltip * Update ProbeVolumeUI.Skin.cs * Fixed the point distribution for the diffuse denoiser sometimes not being properly intialized. #6194 * Fixed the bad blending between the sun and the clouds (case 1373282). #6193 * Fix shadow mask fade and optimize it at same time (#6083) * [HDRP][Path Tracing] Minor fix for SSS when combined with fog (#6215) * Minor fix for SSS + fog. * Comments. * Update 1401_HairGraph_Area_Light.png * update screenshots Co-authored-by: Kleber Garcia <kleber.garcia@unity3d.com> Co-authored-by: gmitrano-unity <89797527+gmitrano-unity@users.noreply.github.com> Co-authored-by: anisunity <42026998+anisunity@users.noreply.github.com> Co-authored-by: John Parsaie <johnpa@unity3d.com> Co-authored-by: Pavlos Mavridis <pavlos.mavridis@unity3d.com> Co-authored-by: Sean Puller <43151199+SeanPuller@users.noreply.github.com> Co-authored-by: Sean Puller <sean.puller@unity3d.com> Co-authored-by: Adrien de Tocqueville <adrien.tocqueville@unity3d.com> Co-authored-by: Emmanuel Turquin <emmanuel@turquin.org> Co-authored-by: Antoine Lelievre <antoinel@unity3d.com> Co-authored-by: emilybrown1 <88374601+emilybrown1@users.noreply.github.com> Co-authored-by: FrancescoC-unity <43168857+FrancescoC-unity@users.noreply.github.com> Co-authored-by: RemyUnity <32760367+RemyUnity@users.noreply.github.com> Co-authored-by: slunity <37302815+slunity@users.noreply.github.com> Co-authored-by: James-Burr-Unity <61244495+James-Burr-Unity@users.noreply.github.com> Co-authored-by: Torbjorn Laedre <271210+tlaedre@users.noreply.github.com>
Purpose of this PR
This PR adds an improved method for supporting rectangular area lights for hair.
Due to lack of support for LTC with anisotropic models, we have up until now fallen back to the GGX LTC for hair. This PR tries to improve on this by instead deferring to a "Representative Point" as a stop-gap method for both the Approximate (Kajiya) and Physical (Marschner) based model until further research is given for LTC.
The result of this work is that we should now be much closer to our references.
Below is some results for our approximation for Physical.
And here is some results for our approximation for Approximate.
[TODO IMAGE]
Performance
Performance-wise this seems like a slight win over LTC for Marschner model and a pretty significant win for Kajiya. Additionally, I measured the MRP method with and without the brute force solid angle computation and did find a measurable difference, but in both cases these still resulted in lower times than the LTC, so I think this is good justification to stick with the brute force solid angle route.
Performance metrics were captured from a standalone Windows built with an NVIDIA Quadro RTX 8000, at a 3840x2160 resolution, 8x MSAA.
Test scenario scene. Left Kajiya, right Marschner.

Testing status
I manually verified the following behaviors:
Updated the hair area light graphics test to reflect the improved area light support, as well as added more coverage for the marschner model. Local tests are passing + launched yamato.
Comments to reviewers
I ended up finding a reasonable way to approximate Kajiya with this approach. It doesn't exactly use MRP, but instead just treats the area light as a normal analytic light and modulates the roughness automatically based on the solid angle. It required some tuning to make sure we are in good agreement with the reference.