-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Fix Area Light Specular Over-Brightness #22372
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?
Conversation
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
BeforeScreen.Recording.2026-01-04.at.2.11.09.AM.movAfterScreen.Recording.2026-01-04.at.2.11.44.AM.mov |
|
Yay! Progress towards finally fixing our specular highlights is huge. I've marked this as Controversial because I want SME-Rendering to decide whether we ship this as a stop-gap, or wait for a better fix (probably Linear Transformed Cosines) to avoid altering the appearance of this twice for our users. |
|
Per discussion in the Discord thread I opened to discuss this, consensus seems to be that is safest to ship in 0.19, but a last minute 0.18 fix would be tolerable. Leaving out of the 0.18 milestone, but @cart or @mockersf can overrule me if they feel strongly. The assorted experts feel strongly that we should ship this, and not wait for LTC to further improve things. |
|
Can you link me Karis 2013 (ideally the part of it where it says to do what you're doing)? Also it'd probably be good to mention that linearly transformed cosines is a better solution in the comment you left, preferably with a link so that people who want to contribute the right solution know where to look. |
| // This is a modification to Karis 2013 for area lights to fix an issue where the specular reflection on smooth materials | ||
| // looks too rough and dim. We lerp between the base roughness and Karis2013 roughness with a lerp factor tuned by looking at reference renders. | ||
| // The goal is to preserve sharp specular highlights on smooth materials, without blowing out specular highlights on rough materials. | ||
| let cc_lerp = 1.0 - (1.0 - clearcoat_a) * (1.0 - clearcoat_a) * (1.0 - clearcoat_a) * (1.0 - clearcoat_a); |
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.
Would you mind putting these selected lines into a function to deduplicate them? Otherwise I can see someone in the future tweaking them at one place and not the other
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.
Mmm, and with an intermediate variable this a^4 could be done in two operations instead of 3.
|
@pcwalton looks like page 14 of https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
This is the reason why the commented out code is... commented out.
The pages after that deal with the sphere light formula used here: with the exception of the custom modification |
|
|
||
| // a' = saturate( a + sourceRadius / (2 * distance) ) | ||
| // see Karis 2013 | ||
| let a_prime = saturate(a + light_position_radius / (2.0 * distance)); |
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.
Karis talks about 3.0 * distance, not 2.0 * distance. Assuming this is intentional on your part, it would be good to add a comment about this :)
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've seen this both ways, I think there is an error in some slides/papers, not sure which is correct.
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.
Add a link to https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf and say "page 14".
janhohenheim
left a comment
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 don't have thaaaaat much knowledge here, but from comparing it with the paper it looks correct, and the manual tweak on top looks good in your test scenes :)
pcwalton
left a comment
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.
Awesome, let's get this in. Big improvement that addresses a long-standing problem.
|
|
||
| // a' = saturate( a + sourceRadius / (2 * distance) ) | ||
| // see Karis 2013 | ||
| let a_prime = saturate(a + light_position_radius / (2.0 * distance)); |
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.
Add a link to https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf and say "page 14".
| // This is a modification to Karis 2013 for area lights to fix an issue where the specular reflection on smooth materials | ||
| // looks too rough and dim. We lerp between the base roughness and Karis2013 roughness with a lerp factor tuned by looking at reference renders. | ||
| // The goal is to preserve sharp specular highlights on smooth materials, without blowing out specular highlights on rough materials. | ||
| let lerp = 1.0 - (1.0 - a) * (1.0 - a) * (1.0 - a) * (1.0 - a); |
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.
As mentioned by others, factor this out into a function. Also, this would be faster:
let inv_a_sq = (1.0 - a) * (1.0 - a);
let lerp = 1.0 - inv_a_sq * inv_a_sq;(There's no need to pull the 1.0 - a into a variable as CSE shader optimizations will do that automatically.)
|
|
||
| // This is a modification to Karis 2013 for area lights to fix an issue where the specular reflection on smooth materials | ||
| // looks too rough and dim. We lerp between the base roughness and Karis2013 roughness with a lerp factor tuned by looking at reference renders. | ||
| // The goal is to preserve sharp specular highlights on smooth materials, without blowing out specular highlights on rough materials. |
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.
Mention that you want linearly transformed cosines as the "real" solution and preferably provide a link. Might as well add a link to this PR too so people who want to improve this can see the discussion.



Objective
Solution
a_prime) specular roughness instead of the base roughness. This allows specular to correctly broaden and fade with distance per Karis 2013.Testing
Reference (Blender)
Before
After
Sharp Reference (Blender)
Sharp Before
Sharp After
Showcase