Cloned ShaderMaterial won't upload its uniform textures
See original GitHub issueDescribe the bug
ShaderMaterial.clone()
fails? to clone texture uniforms to cloned one.
The intention of “?” above is I don’t know I should treat this as a bug or an intended behavior.
The behavior is counter-intuitive anyway imo.
Inside the code
Here is what ShaderMaterial.clone()
will do:
and here is how the cloneUniorms
clone textures:
This will leave .version
of cloned textures to be 0
.
Constructor of texture sets version to 0, and clone does not change the value.
And this leads to not upload assigned textures to GPU.
Reproducing the issue
I’ve made a working example that triggers the issue.
https://glitch.com/edit/#!/grand-plume-windflower
Workaround
There is a workaround code commented out in the Glitch example above.
Manually copying uniform textures to the cloned one will resolve the issue.
Setting .needsUpdate
of cloned textures will also resolve this.
Expected behavior
I have to ask first whether the current behavior is intended or not. If this is not intended, I would like to make it ( reference copy || bump .version
) these uniform textures when ShaderMaterial.clone()
is called.
Detailed context which probably doesn’t matter for you
I’m doing the development of three-vrm.
I was trying to bump three.js version from r126 to r133.
three-vrm 1.0 uses extended ShaderMaterial
(MToonMaterial
namely) and a GLTFLoader plugin which loads the material.
(my current working branch is #1.0
if you’re interested)
In GLTFLoader, there is a code which clones materials for corresponding material variants:
Recently, one of variant conditions are changed from useVertexTangents
to useDerivativeTangents
and this triggers the issue for the first time for us.
PR: https://github.com/mrdoob/three.js/pull/22584
Since this issue has a workaround it can be resolved by our side but it takes a whole business day to resolve this 😭 Understandable difficulty since we’re using ShaderMaterial in an unusual way and there is no other users who combines ShaderMaterial with GLTFLoader plugins…
Platform
- Device: *
- OS: *
- Browser: *
- Three.js version: r133, at least. I don’t see anyone changing these codes recently
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (2 by maintainers)
Top GitHub Comments
Closed via #23637.
I don’t think there will be a solution for the sync pattern mentioned in https://github.com/mrdoob/three.js/pull/23637#issuecomment-1057924336. However, cloning textures in the callback function or by using async/await should now work.
Sorry, I have described the issue not correctly. It’s about this line:
https://github.com/mrdoob/three.js/blob/e1ead8c5c2eb2395942f5e7d9af7240befc5d729/src/renderers/webgl/WebGLTextures.js#L367
Let’s say you have two textures A and B. A has version
1
and B has version0
. The user loads texture B viaTextureLoader
and then copies B to A in theonLoad()
callback. IfTexture.copy()
honors the version, A will still have a version of1
and thus no upload will be executed.