-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
Improve MeshPhysicalMaterial transmission support #21884
Conversation
@takahirox Thanks for this! :-) The previous transmission implementation -- which was just a stub -- looked like this when transmission was set to 1. Now, it darkens when transmission is set to 1... More light should transmit, not less, no? |
I used raw.githack.com to run this sample. However, the result was not as shown in the thumbnail on the left. https://rawcdn.githack.com/takahirox/three.js/d6df4b39033dcf42c139dcef9c700b18880774d1/examples/index.html?q=gltf#webgl_loader_gltf_transmission The environment tested was Windows 10 + RTX 2060 + Chrome 90. |
@cx20 raw.githack.com doesn't work in this case. I'll try to merge this ASAP. |
// transmission | ||
|
||
let _transmissionRenderTarget = null; | ||
const _transmissionSamplerSize = new Vector2( 1024, 1024 ); // Should be configurable? |
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.
Shouldn't this be the same as the output render dimensions? Without refraction, the transmission lines up exactly with the viewport.
const transparentObjects = currentRenderList.transparent; | ||
|
||
if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera ); | ||
if ( transmissiveObjects.length > 0 ) renderTransmissiveObjects( opaqueObjects, transmissiveObjects, scene, camera ); |
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.
Isn't there some way we could not have to render the opaque objects twice? It seems like we could just copy the previous buffer into the tranmissionSamplerMap.
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.
With WebGL2 we'll be able to avoid rendering twice, but with WebGL 1 we can't have antialias when rendering into a render target 😕
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.
Well, wouldn't we still be able to take the normal anti-aliased framebuffer we just rendered the opaque objects into and copy that into the transmissionSamplerMap
for the next pass? Instead of rendering it all over again? This would also remove the question around what size the samplerMap should be.
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.
Can WebGL 1 generate mipmaps for non-power-of two textures? The current implementation uses the lower level mips for roughness transmission.
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.
AFAIK, it can't.
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.
Ah yes, forgot about that. Could we sample it into a power-of-two texture, instead of a pure copy?
vec3 f0 = vec3( pow( ior - 1.0, 2.0 ) / ( pow( ior + 1.0, 2.0 ) ) ); | ||
vec3 f90 = vec3( 1.0 ); | ||
|
||
vec3 f_transmission = totalTransmission * getIBLVolumeRefraction( |
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.
Wow, this isn't just tranmission support, it's also volume and ior? Awesome!
if ( json.transmission !== undefined ) material.transmission = json.transmission; | ||
if ( json.thickness !== undefined ) material.thickness = json.thickness; | ||
if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; | ||
if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); |
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.
Ah, I see. This can support the glTF volume and ior extensions (which are just going in now for ratification), but we haven't yet added these to GLTFLoader. That will be exciting!
Thanks for the report. Yeah, I think transmission = 1 should look more transmissive. I'll take a look... |
@takahirox I understand your use of the glFT fidelity test case, but IMHO, I'd leave that for glTF, and instead focus on enhancing the GUI (and model, if necessary) in the current three.js transmission test case. By being able to vary the parameters, one can see if the new shader is working correctly. |
Excellent work @takahirox! I'm going to merge this and try using |
Thanks! |
I tried the latest version of the three.js library and glTF Loader with gltf-test. Click on the screenshot below to see a sample.
|
@takahirox Can you recheck the |
I tried using copyFramebufferToTexture but seems like the render target needs to be the same size as the framebuffer (which is not power of 2 and everything breaks...) I guess we'll need WebGL 2 for that? |
@takahirox Seems like Safari is not liking the glsl in this PR... Any ideas? |
Safari doesn't support WebGL2 and GLSL3 yet, does it? It seems I should have written And we need to add the following lines if we use
https://developer.mozilla.org/en-US/docs/Web/API/EXT_shader_texture_lod |
@takahirox Thanks! 90abd4f |
Good catch. In the current shader, I first apply the The problem is Perhaps |
@takahirox I tried to figure out how transparent Plastic material work. |
@mrdoob I compared the results before and after the fix in #21894.
|
Right, you can't tell. That test case is not very useful for debugging. It is too complex. What are the material settings, for example? |
@emackey Do you have any advice for us? |
@cx20 A test case with a GUI, similar to https://threejs.org/examples/webgl_materials_physical_transmission.html, is much more useful for determining if the shader is physically plausible. IMHO, of course. :-) |
I agree this particular glTF model mixes test cases without fully indicating which is which. In the sphere shown here, For what it's worth, @cx20's "after" image looks correct to me, because I can no longer see the checkerboard cloth through half of the swirls (those are the metallic ones). So I believe this matches the spec for transmission in glTF. But given infinite time, yes there should be a clearer glTF test model, where a metallic transmissive sphere is compared to a metallic non-transmissive sphere, and a dozen other such tests. |
We already have |
That's great! I'm looking at this from the Khronos side, where we (3D Formats) want to test visual consistency of glTF among a number of different rendering engines, including ThreeJS. |
@takahirox definitely! 👍 |
@takahirox Updated the release notes! |
With all due respect, I still do not think this implementation is physically plausible. A fully-transmissive, white material is not that dark or opaque. I stand by #21884 (comment). https://threejs.org/examples/webgl_materials_physical_transmission.html |
@whatisor any ideas? |
@takahirox I think your new tuning needs to consider Metallic factor.
|
Thanks for the comment.
It means #21975, doesn't it?
Yes, it does. The screenshot of the both metallic and transmission are 1. It is no transparent. |
Ah, sorry the screenshots in #21884 (comment) are bit old. |
Super cool! I love this |
Related issue: #16977, #21000
Description
Sorry for the late but this is a PR for improving
MeshPhysicalMaterial
transmission
support.The screenshot of a new glTF transmission example.
Changes
thickness
,thicknessMap
,attenuationDistance
, andattenuationColor
properties toMeshPhysicalMaterial
.webgl_loader_gltf_transmission
example.transmission_(pars_)fragment.glsl.js
which are primarily based on glTF-Sample-Viewer shader codes. Integratetransmissionmap_(pars_)fragment.glsl.js
with them.WebGLRenderer
. Refer to Intent to implement/contribute Enterprise PBR improvements #16977 (comment) for the detail.Notes
KHR_materials_ior
andKHR_materials_volume
extension supports inGLTFLoader
. I would make a follow up PR if this change is merged.Limitations