Skip to content

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

Merged
merged 20 commits into from
Nov 4, 2021

Conversation

johnpars
Copy link
Contributor

@johnpars johnpars commented Oct 27, 2021

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.

image

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.

Model Area Light Method Forward Opaque Time Per-Groom (ms)
Marschner (+Multiple Scattering) MRP, Brute Force Solid Angle 1.31
Kajiya-Kay MRP, Brute Force Solid Angle 0.97
Marschner (+Multiple Scattering) MRP, Optimized Solid Angle 1.27
Kajiya-Kay MRP, Optimized Solid Angle 0.89
Marschner (GGX) LTC 1.57
Kajiya-Kay (GGX) LTC 1.43

Test scenario scene. Left Kajiya, right Marschner.
image


Testing status

I manually verified the following behaviors:

  • Varying area light shapes and orientations are in good agreement with the reference.
  • Cookie support.
  • Barn door support.
  • Shadow support.

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.

1401_HairGraph_Area_Light


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.

@johnpars johnpars added the HDRP label Oct 27, 2021
@github-actions
Copy link

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.
Link to Yamato: https://unity-ci.cds.internal.unity3d.com/project/902/
Search for your PR branch using the search bar at the top, then add the following segment(s) to the end of the URL (you may need multiple tabs depending on how many packages you change)

HDRP
/jobDefinition/.yamato%2Fall-hdrp.yml%23PR_HDRP_trunk
With changes to HDRP packages, you should also run
/jobDefinition/.yamato%2Fall-lightmapping.yml%23PR_Lightmapping_trunk

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.

@johnpars johnpars requested review from a team, sebastienlagarde, kecho and robcupisz October 27, 2021 20:46
@@ -161,6 +161,9 @@ public struct BSDFData

public float perceptualRoughnessRadial;

// Normalization factor for area lights.
public Vector3 distributionNormalizationFactor;
Copy link
Contributor Author

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)
Copy link
Contributor Author

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
Copy link
Contributor Author

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


float3 L;

if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_HAIR_MARSCHNER))
Copy link
Contributor Author

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
Copy link
Contributor Author

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
Copy link
Contributor Author

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.

Copy link
Collaborator

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?

Copy link
Contributor

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
Copy link
Contributor Author

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);
Copy link
Contributor Author

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.

@@ -1063,7 +1291,11 @@ DirectLighting EvaluateBSDF_Area(LightLoopContext lightLoopContext,
}
else
{
#if 0
Copy link
Collaborator

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?

// 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.
Copy link
Collaborator

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?

Copy link
Contributor

@kecho kecho left a 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!

@johnpars
Copy link
Contributor Author

johnpars commented Nov 2, 2021

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.

@johnpars johnpars marked this pull request as ready for review November 2, 2021 14:22
@johnpars
Copy link
Contributor Author

johnpars commented Nov 2, 2021

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)
Copy link
Contributor

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

@sebastienlagarde sebastienlagarde merged commit d5bdfdb into master Nov 4, 2021
@sebastienlagarde sebastienlagarde deleted the HDRP/hair-mrp-area-lights branch November 4, 2021 09:18
@sebastienlagarde
Copy link
Contributor

@qa: Merging to 22.1, the coverage by John is already great.

alelievr pushed a commit that referenced this pull request Nov 4, 2021
* 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
Copy link
Contributor

@JMargevics JMargevics left a 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. ✔👍

sebastienlagarde pushed a commit that referenced this pull request Nov 7, 2021
* 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
sebastienlagarde added a commit that referenced this pull request Nov 7, 2021
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants