Skip to content
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

Fix depth buffer access in SSS pass & fix numerical robustness of packFloatInt16() #2553

Merged
merged 2 commits into from
Aug 22, 2022

Conversation

MoritzBrueckner
Copy link
Collaborator

This PR fixes two related issues mentioned in https://forums.armory3d.org/t/personal-website-made-with-armory/4723/35:

  1. The SSS pass tried to read from the depth buffer that was still bound to a different render target. I'm not exactly sure which change caused this issue to appear (according to the forum post it didn't happen last year), but it works now.

  2. The implementation of packFloatInt16 in gbuffer.glsl had some numerical robustness issues: a matid of 2 and a metallic value of 0.0 would result in a packed float value of 0.125, which then got unpacked into matid = 1 and metallic = 1.0 because both packed representations are very close to each other.

    My new implementation does not have this issue since the encoded output is basically an integer stored in a float. Unfortunately we cannot use uintBitsToFloat here since possible NaN representations would result in undefined behaviour, so instead the packed bytes are converted back to a valid floating point value. As a result, the precision will be slightly worse for "large" integers than with the old implementation, but even then the worst case error should not be larger than ~0.008 if I'm not mistaken, so we should be fine (the largest currently used matID is 2 anyways I think). In a visual comparison of a color ramp that controls the metallic value, the color banding looks exactly the same for both implementations for a matID of 0. The packed integer value should be exactly preserved.

    I also removed the packFloatInt8 implementation which was not used (anymore?). If there was a reason for keeping it (or you think that my new packing implementation is not good), I can reverse this change. We need to find another solution then, however.

I tested the changes on html5, windows-krom and windows-hl (DirectX and OpenGL), with SSS materials, emission materials and regular materials.

sss_pass_y could not read from "_main" since the depth buffer was also still bound to the "tex" render target.
In the previous implementation, a matid of 2 and a metallic value of 0.0 would result in a packed float value of 0.125, which then got unpacked into matid = 1 and metallic = 1.0. The new implementation does not have this issue, although the principle is basically the same.

Also removed the packFloatInt8 implementation which was not used (anymore?)
@MoritzBrueckner MoritzBrueckner added the Release Notes: Fixes A pull request that fixes something. Used to generate release notes. label Aug 20, 2022
@luboslenco luboslenco merged commit b459da3 into armory3d:main Aug 22, 2022
@luboslenco
Copy link
Member

Awesome!

@MoritzBrueckner MoritzBrueckner deleted the fix-sss branch August 22, 2022 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release Notes: Fixes A pull request that fixes something. Used to generate release notes.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants