-
-
Notifications
You must be signed in to change notification settings - Fork 147
Add GGX multiscatter compensation with Cycles albedo method #697
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
base: main
Are you sure you want to change the base?
Add GGX multiscatter compensation with Cycles albedo method #697
Conversation
Implements physically-based multiscattering for rough surfaces by simulating a random walk on the microsurface structure, allowing rays to bounce multiple times within microfacets before escaping. Implementation details: - Added ggxMicrosurfaceScatter() function that performs random walk - For rough surfaces (roughness > 0.2), rays can bounce 2-4 times within microsurface - Each bounce samples a new microfacet normal using VNDF - Fresnel is accumulated at each bounce for proper colored metals - Russian roulette termination prevents infinite loops - Throughput is applied to the final scatter result This approach uses explicit microsurface scattering (Heitz et al. 2016, Xie & Hanrahan 2018) rather than analytical compensation methods, which is the correct approach for pathtracers. Unlike rasterizer-based compensation formulas (e.g., Kulla-Conty), this method works with the pathtracer's recursive ray tracing rather than against it. Visual impact: - Rough metals: Slightly brighter and more saturated at grazing angles - Rough dielectrics: Better energy conservation, less darkening at high roughness - Smooth surfaces: No change (falls back to single-scatter GGX) The implementation only activates for rough surfaces where multiscatter has visible impact, providing minimal performance overhead. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
27114fb to
e67d3bf
Compare
|
Thanks! I'll take a look at this more in depth when I have a chance. There has been some pretty bad energy loss for metallic materials, unfortunately. Do you mind doing a comparison of the furnace test, as well? See here. Lastly - I know this is from Claude but do you have a reference implementation for these new functions? |
|
Updated PR description. |
|
I just found this other PR: #349 How come you didn't merge that one back then? |








I was working on improving three.js' PBR implementation and while I was using the pathtracer as reference I noticed rough materials were getting darker. I now know that that's because lack of multiscattering.
I asked Claude if it could implement multiscattering in the path tracer, and after a few tries this is what he did:
Description
Implements GGX multiscatter energy compensation to fix energy loss in rough surfaces. Uses Blender Cycles' albedo-based approach to add back missing energy as a diffuse-like multiscatter lobe.
Implementation
0.806495 * exp(-1.98712 * r²) + 0.199531to estimate single-scatter energy capture(1 - albedo) * Favg / πas a diffuse-like multiscatter termApproach
This implementation uses an analytical compensation method rather than explicit random-walk simulation. The approach estimates how much energy single-scatter GGX captures using a fitted albedo curve, then adds the missing energy back as a Lambertian-like lobe scaled by average Fresnel.
This is simpler and faster than full microsurface random-walk methods while providing good energy conservation. The fitted albedo values come from Blender Cycles' ground-truth precomputed data.
Visual Impact
References
intern/cycles/kernel/closure/bsdf_microfacet_multi.h