-
Notifications
You must be signed in to change notification settings - Fork 56
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
Make sure that semi-opaque objects are rendered correctly #6
Comments
After investigating the rendering in Cesium, it seems like the rendering of semi-opaque objects in JglTF is "correct", as far as one can reasonably say this. Cesium uses Order-Independent Transparency to cause the objects to appear "nicely", but without OIT, they look exactly like the objects in JglTF. Particularly, when the input file says
then the results in JglTF and Cesium look "equally wrong" (as in the first screenshot above). If the input file said
then the objects would appear more nicely, as in the second screenshot above. The same applies to the "boxes" in the VC model, which have been discussed in KhronosGroup/glTF#576 : When disabling OIT in Cesium, then the boxes are visible there as well. So the result is what the result is, according to the input file, and this issue can be closed for now. |
The role of premultiplied alpha has to be investigated. In WebGL, it is ENabled by default. In Desktop OpenGL, it is DISabled by default. The colors that are delivered by the fragment shader have to be treated differently based on this setting. Since the fragment shader cannot be modified by the renderer, this may boil down to some (ugly, ugly) tweaks and workarounds of interpreting the |
I think that for a fragment shader that assumes premultiplied alpha, the computation at the end should be
and not
(because the |
After having read
OR
Both choices will not affect the renderer, but are solely determined by the input file. Specifically: The Side note 1: The VC model uses
in the shader, and I think that this does not properly take into account the Side note 2: For the non-premultipled case, the blend functions may have to be
so that multiple semi-opaque objects are "stacked" properly - but this likely only makes sense when they are rendered in the right order, which cannot be guaranteed. With both approaches sketched above, the results look "correct", as in the second screenshot. (Corollary: The VC model contains an error. I'm open for arguments here) |
The line that I currently consider to be "wrong" in the sense of an implementation of premultiplied alpha is probably caused by https://github.com/KhronosGroup/COLLADA2GLTF/blob/5cbbe4674c16aa05cc613d8b7c50f4557b5af611/shaders/commonProfileShaders.cpp#L1207 |
(EDIT: Updated to fix a bug in the sample and the images)
Most of the information about how semi-opaque (or semi-transparent) objects should be rendered is encoded directly in the glTF asset. This information is contained in the
technique.states
andtechnique.states.functions
. For example, thetechnique.states
contains information about whetherGL_BLEND
is enabled or not. Andtechnique.sates.functions
contains information about the blend equation and blend functions.(The only information that is not contained in the asset explicitly is the order in which the objects have to be rendered. Determining this order is far from trivial, and Order-Independent Transparency is an active research topic. For the simplest case, one has to make sure that opaque objects are rendered before semi-opaque objects are rendered. For the tests that are related to this issue, I implemented this locally in the jgltf-viewer, but these changes are not yet committed until this issue is resolved)
At the bottom of this issue, there is a glTF asset intended for testing the opacity handling.
The red triangle is rendered fully opaque, using the
"opaqueTechnique"
.The five blue triangles are rendered with different materials that use the
"semiOpaqueTechnique"
:"semiOpaqueMaterial0"
with an opacity of 0.0 (fully transparent)"semiOpaqueMaterial25"
with an opacity of 0.25"semiOpaqueMaterial50"
with an opacity of 0.5"semiOpaqueMaterial75"
with an opacity of 0.75"semiOpaqueMaterial100"
with an opacity of 1.0 (fully opaque)By default, the
technique.states.functions
of thesemiOpaqueTechnique
contain the following settings:The result is shown in this image:
The materials are ordered from upper left to lower right. So the upper left blue triangle is supposed to be fully transparent. Obviously, the result is utterly wrong.
Intuitively, I'd expect the values for the blend function to be
Because the pixels should be written with the source alpha, and the existing background pixels should be "blended out" or "overwritten" depending on the source alpha. The result looks correct for me:
I could now start trying different values for the RGB- and the alpha part, but I'm not sure whether "trial and error" will help here. The tool at http://www.andersriggelsen.dk/glblendfunc.php might be helpful to try things out, but I'm not sure how to systematically figure out the right settings, because I'm not entirely sure what the result is supposed to look like at all...
The glTF asset used for testing. The buffer data is embedded. The shaders are given below.
The
opacity.vert
vertex shader:The
opacity.frag
fragment shader:The text was updated successfully, but these errors were encountered: