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
Add cutoff to mip and minip volume projection for fragment discard #2308
Conversation
What is the actual use-case for this? These cutoffs feel to me as ideally being inf/-inf (I wonder if its safe to actually use these values in a shader), and making them settable feels odd to me. Maybe these use-cases could be solved differently, e.g. by setting clim and using a colormap with alpha=0 in some places. That is more work, but might be more correct. Thought? |
I agree that by default the cutoffs should be the min and max possible values of the data type... Not sure if Notice that on main they are harcdoded to Yes, colormap withg alpha would be the right way to do it, if only transparency in vispy wasn't broken :P as you may remember, I went down the deferred rendering rabbit hole to implement OIT, but that's a massive amount of work and probably not gonna happen any time soon (if at all before vispy 2.0). |
I think it should work by doing something like this near the end of the shader (after the colormap, at least):
|
Note that this PR does change behavior no matter what we choose (to keep the current limits or to use the extremes), because previously if the ray casting detected only a maximum that was lowe than |
This would work for |
Right, due to the linear interpolation of the colormap. mmm ...
Yeah, I agree that the current behavior was technically incorrect. After some more thought I can see how it makes sense to be able to hide/discard rays that don't meet a certain value in MIP, and this seems like the best way to do this. 👍 |
So would you suggest keeping |
Shall we try using inf? I'm a bit scared of odd results on specific drivers, but we can revert if we do. |
Living on the edge 🤘 |
It seems that our best bet is to use max and min float values... the internet says:
Inf can be obtained apparently with |
Isn't that the smallest representable decimal? I mean, shouldn't the negative of the max be the minimum? Edit: That number is "The minimum positive normal value", but zero would still be less than that. |
Yup, oops, I just found the same as well! Googled too superficially. Obviously they should be opposites. |
Turns out we can rely on |
What happens if you do |
Yeah... I would hope that floats are converted (and clipped) somewhere in the gloo or |
I don't think we do any of that in vispy - it's up to the driver to do (or not do) this. |
Similar experience here with NaN. The CI jobs that use NaNs in the images are xfail because the GL drivers on the CI machines apparently can't handle NaN. On those machines NaN is just replaced with 0 if I remember correctly. |
So, I added some tests to see if things are working properly. I get failures here, but I think they are correct. I'm a bit tired so I might have done something very wrong... |
Ok, I tracked down the issue as far as I could. It turns out we're back to canvas sizing issues, like some time ago in another PR (forgot which...). Basically, very small canvas sizes and qt seem to not play well together. Things seem to go awry when the canvas context manager is entered, and Try this on your machine: from vispy.scene import SceneCanvas
c = SceneCanvas(size=(40, 40))
c.size # output is correct
c.show()
c.size # output is wrong In fact, it seems that anything below EDIT: this was meant as a comment to #2305, but likely applies here too. |
vispy/visuals/volume.py
Outdated
if (maxi > -1) { | ||
gl_FragColor = applyColormap(maxval); | ||
} |
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.
Keeping in mind that I don't know much about volume rendering, is this just an optimization or does it actually fix things showing up when they shouldn't be there?
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.
It fixes things to behave the same as the other visuals. Without this change, it was defaulting to always setting the value from the zeroth step of the raycasting, even when there was nothing (i.e: beyond the cutoff). Basically, the cutoff was not being used :P
Strange find. Nice job. Any idea why the other tests that use a 40x40 canvas size work? |
I think it's just by luck and trial and error. I've had issues before with this, and now it's clear why. When this last happened, I changed my approach until this was no longer causing issues (for example by dynamically calculating the center of the rendered image rather than passing a specific index). Other tests simply don't care because the whole canvas is supposed to be the same color, or they just check that a color is shown somewhere but don't care where. For the future, I suggest we never use below 75x50 to avoid any issues :P |
Sounds good! |
Just a note: we should double check in between merging this and #2305, cause there's probably going to be some conflicts. I would suggest merging this last. |
All good from my side; conflicts are solved and tests pass locally. @djhoese let me know if there are unclear things; otherwise I think this is ready to go in as well! |
Given the passing tests and the prior approval from Almar, let's merge this... |
This PR takes out some code from the solution to the issues in #2305.
Specifically, see this comment and this other comment.
In practice, the new attributes allow to set a lower bound to MIP projection (and higher bound to MINIP) beyond which fragments are discarded.