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

GLTFLoader: Support KHR_materials_transmission physically-based transparency #21000

Closed
Doerge opened this issue Jan 4, 2021 · 50 comments
Closed
Milestone

Comments

@Doerge
Copy link

Doerge commented Jan 4, 2021

Describe the bug

The extension KHR_materials_transmission does not semi transparent materials from a .glb.

To Reproduce

Steps to reproduce the behavior:

  1. Get the reference glb from here https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/TransmissionTest
  2. Load it with threejs gltf loader.
  3. The parts of the geometry that are supposed to be semi-transparent are instead 100% opaque. Only 100% transparency is respected. See screenshots below.

Live example

https://jsfiddle.net/jt6ywhs5/12/

Expected behavior

Semi-transparency and transmission works.

Screenshots

Reference:
Screenshot 2021-01-04 at 17 52 32
Threejs:
Screenshot 2021-01-04 at 18 22 10

Platform:

@donmccurdy
Copy link
Collaborator

donmccurdy commented Jan 4, 2021

three.js only implements a small part of the KHR_materials_transmission extension today, which is why we haven't listed the extension in the docs yet. There are more transmission features left to implement. See #16977 for a bit more about this. Also note that using an environment map is critical for physically-based reflections and transparency.

@Doerge
Copy link
Author

Doerge commented Jan 4, 2021

Ah I see. I was a bit too fast then. I landed on the source code through Google, and thought it was already there. Sorry!
Yeah, I didn't bother with an env map, since it was clear the semi transparency wasn't working. Was hoping it was just a setting but alas! Feel free to close this issue if it's already tracked elsewhere.

@donmccurdy
Copy link
Collaborator

Let's keep this open — #16977 is a pretty broad issue so I think it's good to have something specifically tracking KHR_materials_transmission.

@donmccurdy donmccurdy changed the title KHR_materials_transmission with a glb doesn't load semi-transparency properly. GLTFLLoader: Support KHR_materials_transmission physically-based transparency Jan 4, 2021
@donmccurdy donmccurdy changed the title GLTFLLoader: Support KHR_materials_transmission physically-based transparency GLTFLoader: Support KHR_materials_transmission physically-based transparency Jan 4, 2021
@mrdoob mrdoob added this to the r125 milestone Jan 4, 2021
@mrdoob mrdoob modified the milestones: r125, r126 Jan 27, 2021
@mrdoob mrdoob modified the milestones: r126, r127 Feb 23, 2021
@yaroslavnikiforov
Copy link

Is it possible to implement this in three.js using MeshPhysicalMaterial without extension? (like Rough Transmission yellow ball on the reference image)

@donmccurdy
Copy link
Collaborator

No, some changes to MeshPhysicalMaterial would need to be made to support these features.

@yaroslavnikiforov
Copy link

Hi, what is the status of implementing this, is it work in progress? Will it be included in the next release? Thanks.

@donmccurdy
Copy link
Collaborator

Sorry, this is not being worked on right now. If anyone is interested in working on it please let us know. :)

@patricpalmefjord
Copy link

Thank you for the update, I was hoping this enhancement would roll out during March. It would be really useful to have.

@rawwerks
Copy link

i would be happy to subsidize the work if someone has the skills and bandwidth to get KHR_materials_transmission fully implemented in three.js . please reach out if you are interested and available in the coming weeks.

@mrdoob mrdoob modified the milestones: r127, r128 Mar 30, 2021
@Mandoliiin
Copy link

Hi, I'm in real need of this enhancement. Any update when on we can expect this bug to be fixed? Otherwise, is there some workaround I can use to achieve similar effect in the meanwhile? I cannot find anything. Thanks! 🙂

@mrdoob mrdoob modified the milestones: r128, r129 Apr 23, 2021
@rawwerks
Copy link

rawwerks commented Apr 25, 2021

if you can think of anyone who can get this done as a contractor, please send them here: https://www.upwork.com/job/Seeking-talented-javascript-developer-enhance-three_~0153b7a387f184d444/

my intention is to prioritize folks who have already made meaningful contributions to three.js - but at this point i really need to find someone who can knock this out.

@whatisor
Copy link
Contributor

The first issue of current transmission implementation is not yet auto-enable Transparent which makes Alpha meaningful.

#ifdef TRANSMISSION diffuseColor.a *= mix( saturate( 1. - totalTransmission + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) ), 1.0, metalness); #endif

However, currently, other issues I found are:

  • roughness does not work as expected.
  • Alpha map does not work with Metallic
    Screenshot (89)

@whatisor
Copy link
Contributor

whatisor commented May 4, 2021

We decided to follow GLTF Viewer Sample to implement this. There is some point which needs to be considered:

  • Opaque object is considered as an environment/background of others with transmission. Should it be a forced rule in threejs core or just a flexible option of application where the application can choose background/foreground object?
    @mrdoob

KHR_Transmission_v0 1

Source

@whatisor
Copy link
Contributor

whatisor commented May 4, 2021

Improvement points:

  • Refraction with thickness
  • Dynamic background ( adobe is crazy cool with this stuff for supporting by lazy rendering)
    adobe_transmission
    Adobe

@mrdoob
Copy link
Owner

mrdoob commented May 4, 2021

@whatisor I think for now we should just render the opaque meshes into a renderTarget: #16977 (comment)

@whatisor
Copy link
Contributor

whatisor commented May 5, 2021

Yes, agreed. @mrdoob
However, I am also considering how it can become a PR with these modifications and next improvements...

@rawwerks
Copy link

There's a great sneak peek and explanation of the volume refraction here: https://youtu.be/JMiXv2PgGBY?t=2552

@whatisor
Copy link
Contributor

whatisor commented May 15, 2021

Hi, is there some source code available to test? Thanks.

@yaroslavkhudchenko
Forked here : https://github.com/3dgraphicsplus/three.js/tree/KHR_materials_transmission
just build and run threejs example ( gltf extension)

@takahirox
Copy link
Collaborator

Certainly I'd be excited to see both supported in THREE.MeshPhysicalMaterial. :)

I'm thinking of adding the following properties corresponding to KHR_materials_volume parameters

  • thickness
  • thicknessMap
  • attenuationDistance
  • attenuationColor

Note: MeshPhysicalMaterial already has transmission and transmissionMap corresponding to KHR_materials_transmission parameters and ior corresponding to KHR_materials_ior parameter.

@takahirox
Copy link
Collaborator

Made a PR #21884

@yaroslavnikiforov
Copy link

Hi guys! Will it work out of the box like with Babylon, or it will need some additional setup like in the example? With PMREM env map, that toggleOpaque function and calling render twice in an animation loop. Doesn't look like it would be possible to use it, because of 9-10 fps like in the example.

Screenshot 2021-05-26 at 15 25 50

@donmccurdy
Copy link
Collaborator

@yaroslavkhudchenko you can find the three.js example here, the setup is pretty normal:

https://github.com/mrdoob/three.js/blob/dev/examples/webgl_loader_gltf_transmission.html

Physically-based transmission will be more expensive than alpha blending. But your exact framerate will depend on many things. For example, I would expect that using transmission on a smaller area of the viewport will be cheaper than using it on a larger area of the viewport. The best thing to do here would be to test and report issues when this is available.

@mrdoob mrdoob modified the milestones: r129, r130 May 27, 2021
@donmccurdy
Copy link
Collaborator

Fixed in #21884, many thanks @takahirox, @whatisor, @rawwerks and anyone else contributing here. 👏

@takahirox
Copy link
Collaborator

So, the transmission support quality got better with the several PRs.

I'm thinking of adding KHR_materials_volume and KHR_materials_ior extensions support to GLTFLoader next.

I would like to know your opinion about the new example.

1. Model

I'm thinking of using TransmissionRoughnessTest model from glTF-Sample-Models repo because it has transmission, volume, and ior extensions

https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/TransmissionRoughnessTest

Let me know if you know better models.

2. Update the existing example or new Example

I think we have three options.

a. Replacing the model of webgl_loader_gltf_transmission example.

b. Add the new model to webgl_loader_gltf_transmission and allow users to switch models like webgl_loader_gltf_extensions

c. Adding a new example webgl_loader_gltf_volume

I don't have strong opinion. Any preferences?

@donmccurdy
Copy link
Collaborator

@takahirox
Copy link
Collaborator

I knew those two models but unfortunately they don't use KHR_materials_ior extension although the dragon model looks nicer than TransmissionRoughnessTest.

@donmccurdy
Copy link
Collaborator

I'll gladly add IOR to as many models as you want, if you're working on implementing it. 😍

@mrdoob
Copy link
Owner

mrdoob commented Jun 16, 2021

@takahirox

b. Add the new model to webgl_loader_gltf_transmission and allow users to switch models like webgl_loader_gltf_extensions

That sounds like the best option to me 👍

@WestLangley
Copy link
Collaborator

As I said elsewhere, the webgl_loader_gltf_transmission example is not useful to us because the parameter settings are not accessible. There is no way to determine if the code is working properly because we don't know what we are looking at.

That example is useful for comparing three.js to other renderers.

I would remove it from the examples. We have another transmission example with a GUI.

@mrdoob
Copy link
Owner

mrdoob commented Jun 16, 2021

I think it is useful so people can see that we correctly render gltfs that use transmission though.

@WestLangley
Copy link
Collaborator

I think it is useful so people can see that we correctly render gltfs that use transmission though.

Do you plan to add all the examples? https://github.com/cx20/gltf-test#extension-test-models

@emackey
Copy link

emackey commented Jun 16, 2021

I knew those two models but unfortunately they don't use KHR_materials_ior extension

This is one of those wrinkles in the glTF spec that I wasn't able to avoid. The IOR extension merely sets the IOR, which defaults to 1.5 if you don't use the IOR extension. The actual switch for enabling or disabling the refractions themselves is controlled by the thicknessFactor in KHR_materials_volume being zero or nonzero (thin-walled or thick-volume material). It may not be intuitive at first glance, but it makes sense when you take the time to deeply understand the glTF materials system design.

/cc @emackey I don't suppose there is a version of [the Sketchfab mosquito with the new glTF extensions]

Yes, I had built that a while ago as a Khronos-internal test. But the source model is CC-BY and I've been meaning to post in on the sample repo with some nice documentation and credits. Someday soon I hope, unless someone else beats me to it. Bonus points if the proper IOR for amber is looked up and added to the model.

@takahirox
Copy link
Collaborator

I agree with @mrdoob

I think it is useful so people can see that we correctly render gltfs that use transmission though.

We have one example or model per one glTF extension which GLTFLoader support.

@donmccurdy
Copy link
Collaborator

In my mind the three purposes of examples are, from most to least important:

  1. Help users learn three.js
  2. Showcase three.js features
  3. Visual regression tests

The current transmission model mostly does (3), i.e. it's a model designed to test a feature and compare across engines. I don't necessarily think we need one model per glTF extension; ideally we'd cover each extension in unit tests instead. If we have a more visually interesting model for the transmission use case (with or without volume and ior) i think it'd be fine to replace the current one too.

@takahirox
Copy link
Collaborator

takahirox commented Jun 16, 2021

i think it'd be fine to replace the current one too.

I was thinking the similar thing. We have webgl_materials_physical_transmission example which has the parameter GUI then we can test transmission stuffs on it. Instead we can focus on glTF + transmission showcase in webgl_loader_gltf_transmission and we can replace the testing purpose model used in it with a more looking interesting one (maybe that Dragon one? because it's well known by 3D CG folks). Or we can replace the gltf transmission example with a glTF PBR next example (using ToyCar?) as a showcase of glTF PBR next.

@WestLangley
Copy link
Collaborator

webgl_loader_gltf_transmission has the transparent property of each sphere to set to false. Are you aware of that? Is that what the loader should be doing?

Even setting transparent to true, only front-faces show the hot-spot. (This may be a known limitation, but @mrdoob just added support for properly rendering backfaces of double-sided meshes.) There should be two hot-spots.
Screen Shot 2021-06-16 at 1 53 43 PM

There is a tone mapping problem, somewhere...
Screen Shot 2021-06-16 at 1 51 42 PM

@donmccurdy
Copy link
Collaborator

webgl_loader_gltf_transmission has the transparent property of each sphere to set to false. Are you aware of that? Is that what the loader should be doing?

In glTF, a model may specify "transmission+alphaMode=BLEND" or "transmission+alphaMode=OPAQUE". The latter is recommended but not required. The loader is interpreting alphaMode=OPAQUE as transparent=false. It is not a perfect analog, since .transparent controls three things: blend mode, sort order, and two-pass double-sided rendering.

I think you are asking if associated behaviors — other than the blend mode — should apply to transmissive materials, too?

@WestLangley
Copy link
Collaborator

@donmccurdy Thank you for your reply.

I was trying to determine why, when looking at the transmissive sphere, I do not see two hot-spots. To try to determine why, I had to debug the loaded glTF model, because the model parameter settings are obfuscated, and there is no other way to tell what I am looking at.

That is all I was focusing on, but I think your higher-level questions are important.

@coderextreme
Copy link

Hi, I'm in real need of this enhancement. Any update when on we can expect this bug to be fixed? Otherwise, is there some workaround I can use to achieve similar effect in the meanwhile? I cannot find anything. Thanks! slightly_smiling_face

Something like this? https://playcanv.as/p/wQgQBgkE/

@donmccurdy
Copy link
Collaborator

@takahirox this might be a helpful sample and discussion, as well: KhronosGroup/glTF-Sample-Models#319

@takahirox
Copy link
Collaborator

@donmccurdy

Thanks! I will make an example with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests