Skip to content

Conversation

@aevyrie
Copy link
Member

@aevyrie aevyrie commented Jan 4, 2026

Objective

Solution

  • Apply the modified (a_prime) specular roughness instead of the base roughness. This allows specular to correctly broaden and fade with distance per Karis 2013.
  • The only downside of this approach is that specular reflections on smooth materials are over-attenuated. This is a known issue of Karis 2013, and the solution is to implement a popular solution like Linearly Transformed Cosines to handle area lights more correctly.
  • In the meantime, I've applied a correction that lerps between the base roughness and the modified area light roughness, to retain sharpness and brightness for glossy materials. This was tuned from the reference renders.

Testing

Reference (Blender)

image

Before

image

After

image

Sharp Reference (Blender)

image

Sharp Before

image

Sharp After

image

Showcase

image image image image image image image image image image

@alice-i-cecile alice-i-cecile added this to the 0.18 milestone Jan 4, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2026

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!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-22372

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.

@alice-i-cecile alice-i-cecile modified the milestones: 0.18, 0.19 Jan 4, 2026
@aevyrie
Copy link
Member Author

aevyrie commented Jan 4, 2026

Before

Screen.Recording.2026-01-04.at.2.11.09.AM.mov

After

Screen.Recording.2026-01-04.at.2.11.44.AM.mov

@aevyrie aevyrie added the M-Deliberate-Rendering-Change An intentional change to how tests and examples are rendered label Jan 4, 2026
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen X-Controversial There is active debate or serious implications around merging this PR labels Jan 4, 2026
@alice-i-cecile alice-i-cecile added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Jan 4, 2026
@alice-i-cecile
Copy link
Member

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.

@alice-i-cecile alice-i-cecile added X-Uncontroversial This work is generally agreed upon and removed X-Controversial There is active debate or serious implications around merging this PR labels Jan 4, 2026
@alice-i-cecile
Copy link
Member

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.

@pcwalton
Copy link
Contributor

pcwalton commented Jan 5, 2026

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.

Comment on lines +688 to +691
// 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);
Copy link
Member

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

Copy link
Contributor

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.

@janhohenheim
Copy link
Member

janhohenheim commented Jan 5, 2026

@pcwalton looks like page 14 of https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf

image This is the reason why the commented out code is... commented out.

The pages after that deal with the sphere light formula used here:
image
image

with the exception of the custom modification cc_lerp = 1.0 - (1 - a)^4.


// a' = saturate( a + sourceRadius / (2 * distance) )
// see Karis 2013
let a_prime = saturate(a + light_position_radius / (2.0 * distance));
Copy link
Member

@janhohenheim janhohenheim Jan 5, 2026

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 :)

Copy link
Member Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JMS55
Copy link
Contributor

JMS55 commented Jan 5, 2026

Copy link
Member

@janhohenheim janhohenheim left a 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 :)

Copy link
Contributor

@pcwalton pcwalton left a 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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior M-Deliberate-Rendering-Change An intentional change to how tests and examples are rendered S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Uncontroversial This work is generally agreed upon

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Specular from area lights is disproportionately bright

6 participants