-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
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
Prevent division by zero and warn about invalid normal/tangent information #51268
Prevent division by zero and warn about invalid normal/tangent information #51268
Conversation
CC @The-O-King |
Everyone wants:
I didn't explain clearly, the code will consistently generate NaN's from a 0,0,0 input which is a bug IMHO, and will result in undefined behavior. The real issue / problem that is not clearly stated (div by 0) is always consistent with 0,0,0 input as I found in testing, sorry if I didn't make this clear in the PR. (every other value was fine :) ) I'm open to someone suggesting how to remove the division by zero to make it support the 0,0,0 values and passing a 0,0,0 when it's part of the input. Reproduce by ubsan=yes and reimport a model and open the scene. |
Okay, so we have a problem with invalid input to the octahedral compression function, it outputs NaNs if the normal is The problem is that if our compression code returns Unfortunately, the octahedral compression function is made to work with unit-length values in the -1 to 1 range. I.e. there is no valid compressed Vector2 that decompresses to This PR currently checks if the input to Further, the results of Accordingly, we need to do two things:
number 1 should likely be in another PR number 2 would essentially look like adding the follow to
Appendix
The end result is a vector that has the same direction, but a different magnitude from our original. Meaning, if we normalized both values we would get the same Vector ( Let's start from a normalized vector
Well that already looks familiar and we know how it will decompress. |
I agree with what @clayjohn has said so far, and his math is correct, as I mentioned in comments before Vector2(0, 0) is a valid compressed value so we can't map Vector3(0, 0, 0) to it, and Vector3(0, 0, 0) simply doesn't work for this compression scheme Lets normalize the vector returned by oct_to_norm(), and most likely also do that in the shader decompress code as well (scene.glsl) The warning seems like the most reasonable solution to this problem for when Vector3(0, 0, 0) is passed in (as there's no way to get a Vector2 that could map back to it), I don't think the resulting NaN implies that we are "relying" on it, it's just the result of invalid input for the mesh anyways, I mean I guess we could set it to return some "default" normal like Vector2(0, 1) (which maps to Vector3(0, 1, 0)) or something but I don't think that makes the problem any better? |
What are the problems of returning an identity normal that is valid? |
It will result in bogus normals in the shader. In the case of mesh normals, there is no such thing as an "identity normal" or default normal. The function should return a default |
I believe we can get a representation of 0,0,0 in another way I'll make all the recommended changes but also add my idea onto the patch, it should make it tolerant to 0,0,0 normals :) without causing the issue with the compression or the division by zero. should submit it tonight or tomorrow |
29019eb
to
ce0f2ba
Compare
Updated description of PR to include new notes and method used, please check the code it works nicely. 🤣 they should update / amend the paper to allow for this. |
@RevoluPowered I'm not sure about abusing NaNs like this. Can we pass NaNs to the GPU and expect it to have consistent behaviour? I highly doubt it. Remember the edit: See the Vulkan Spec implementations are not required to support NaNs so we may get problems on certain devices. At any rate, I don't see the value in allowing users to use a 0,0,0 normal. 0,0,0 isn't a valid normal and will create NaNs later in the pipeline anyway. |
Catching up late on this, but yeah my tendency would be to agree with @clayjohn and not try to send NaNs. Afaik GPUs are required to not crash when encountering NaN, but their behaviour is undefined, so shouldn't be relied on. (I've heard of a few instances of people abusing NaNs targetting a particular platform, especially a console, but it sounds very dodgy for a general purpose engine). Given the timeline @akien-mga says he hopes to make another beta before going on holiday, I would be in favour of fixing this bug with @clayjohn method first then researching a bit more into the NaNs, because having a divide by zero in the current branch does not seem good and should be closed asap imo. |
This was reported by UBSAN. Many methods were discussed, in the end this has the least evils and will use a 0,0,1 default on decompress. Please see the PR for more info godotengine#51268
ce0f2ba
to
6883d55
Compare
tested now, it's fine :) |
Thanks! |
This was reported by UBSAN. Many methods were discussed, in the end this has the least evils and will use a 0,0,1 default on decompress. Please see the PR for more info godotengine#51268
This was reported by UBSAN. Many methods were discussed, in the end this has the least evils and will use a 0,0,1 default on decompress. Please see the PR for more info godotengine#51268
This was reported by UBSAN.
Many methods were discussed, in the end this has the least evils and will use a 0,0,1 default on decompress e.g. non undefined behaviour.
Follow up PR will fix the source of these normals:
godotengine/godot-proposals#3151