-
-
Notifications
You must be signed in to change notification settings - Fork 517
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
threejs does not handle transparency correctly #31600
Comments
Attachment: threejs.good.transparency.png |
Attachment: threejs.no.transparency.png |
This comment has been minimized.
This comment has been minimized.
comment:1
Attachment: threejs.wrong.transparency.png |
Commit: |
comment:2
I've used the theta,z=var('theta,z')
cb = cylindrical_plot3d(2,(theta,0,2*pi),(z,-5,5), alpha=0.3, color='blue', render_order=-1)
cr = cylindrical_plot3d(1,(theta,0,2*pi),(z,-7,7), alpha=0.3, color='red', render_order=-2)
cv = cylindrical_plot3d(0.5,(theta,0,2*pi),(z,-10,10), alpha=0.5, color='green', render_order=-3)
p = cb + cr + cv
show(p, viewer='threejs') You'll still see issues with self-transparency due to the order in which the faces of each cylinder are drawn. Also, adjusting the render order can conflict with the text sprites, so I try to use negative values. I don't know of a way to automatically set the render order or that it'd even be possible for some arbitrary set of transparent surfaces. But for the self-transparency and text sprite problems I mentioned, perhaps it would be better to just disable writing to the depth-buffer entirely for transparent surfaces and text? I'm trying to think through whether this might result in other graphical glitches itself, since it seems so straight-forward that why wouldn't Three.js do this automatically when you make a material transparent? I've pushed a commit with this change and will attach an example with the same cylinders plus an intersecting opaque surface for comparison. New commits:
|
Attachment: noDepthWrite.html.gz Example with depth write of text and transparent surfaces disabled |
comment:3
Replying to @jcamp0x2a:
It might be for performance reasons. On such a small scene the difference might not be It is known that, in principle, a depth buffer cannot handle multiple transparent surfaces correctly unless they come in a consistent order (front-to-back or back-to-front). Is there some documentation on what threejs does when setting depthWrite: false Maybe the behaviour should be controllable by an option by the user.
The example looks good! |
comment:4
Replying to @guenterrote:
The doc for it is basic, but it looks like it's only ever passed along as-is to WebGL's glDepthMask prior to rendering each object. A bit of the call stack in three.js:
Would want to default to disabling depth write I assume? So the user can toggle on the depth write only if they're having performance problems with lots of transparent surfaces. I'm still struggling to come up a non-performance reason for turning it on, though I have a limited imagination ;) |
comment:5
Replying to @jcamp0x2a:
Joshua, why don’t you ask these questions in the Three.js forum: https://discourse.threejs.org/ |
comment:6
Replying to @paulmasson:
Hi Paul! Thanks for the link to the forum. I'll try to keep it in mind as an additional resource for questions in the future. It looks like something similar to this issue been discussed there quite a bit already. I found ThreeJS and the transparent problem to be an interesting read. The rule of thumb indeed seems to be to disable depth write for transparent objects. I also found GLTFLoader: Use depthWrite=false for transparent materials which seems to support that and makes up my lack of imagination with some links to cases where you'd want the depth-write to remain enabled. There's also a few interesting techniques mentioned in there like screendoor transparency and "Weighted Blended Order-Independent Transparency" that I didn't know about and will have to read up on now. :) |
comment:7
I checked those references, and I must correct myself. This has no effect on performance. (I thought the use of the framebuffer is completely abandoned when setting depthWrite:false.) The effect of For example, the top of the cylinders gives no visual clue whether you can see "into the pipe" from above or whether you look "up" to the pipe from below. (If you view it with tachyon, it really looks much better. Look at the transition between the green and red cylinder in the upper half and in the lower half) Another case is when you have two transparent surfaces (plane) that intersect. Then you probably would like to see the difference, which one is in front and in particular where they intersect and change the order. But I would advocate to switch to disabling depth-write by default. |
comment:8
Here is an example where
But surprise when looking from behind! |
comment:9
Replying to @guenterrote:
Ray-tracing is the future :) |
comment:10
Replying to @guenterrote:
It's listed in the reference manual for the Three.js viewer: https://doc.sagemath.org/html/en/reference/plot3d/threejs.html Cool example :) |
Branch pushed to git repo; I updated commit sha1. New commits:
|
Author: Joshua Campbell |
comment:13
I've added an option and documentation for controlling whether to do the depth-write for surfaces. |
comment:15
Just ran into this problem myself. This fixes it. |
Reviewer: Matthias Koeppe |
Changed branch from u/gh-jcamp0x2a/31600-transparency to |
Here is an example to reproduce it yourself:
Compare
with
As you can see, with
threejs
, when you rotate the picture, on some angles, the transparency is correct, but sometimes there is no transparency at all, and sometimes there is a wrong transparency, see the attached pictures.CC: @egourgoulhon @jcamp0x2a @paulmasson @slel @guenterrote
Component: graphics
Author: Joshua Campbell
Branch/Commit:
515bcf4
Reviewer: Matthias Koeppe
Issue created by migration from https://trac.sagemath.org/ticket/31600
The text was updated successfully, but these errors were encountered: