question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cloned ShaderMaterial won't upload its uniform textures

See original GitHub issue

Describe 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:

https://github.com/mrdoob/three.js/blob/d9af9952fc32c2a1281707946177135b90297aab/src/materials/ShaderMaterial.js#L86

and here is how the cloneUniorms clone textures:

https://github.com/mrdoob/three.js/blob/d9af9952fc32c2a1281707946177135b90297aab/src/renderers/shaders/UniformsUtils.js#L17-L22

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:

https://github.com/mrdoob/three.js/blob/d9af9952fc32c2a1281707946177135b90297aab/examples/jsm/loaders/GLTFLoader.js#L2980

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:closed
  • Created 2 years ago
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
Mugen87commented, Mar 4, 2022

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.

0reactions
Mugen87commented, Nov 26, 2021

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 version 0. The user loads texture B via TextureLoader and then copies B to A in the onLoad()callback. If Texture.copy() honors the version, A will still have a version of 1 and thus no upload will be executed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cloned objects with shader material added not rendering in ...
Instanced meshes render just fine. It's just the cloned meshes causing problems. Any idea what the problem might be?
Read more >
Replicating MeshLambertMaterial Using ShaderMaterial ...
and this is the code that I use to setup my uniforms and create the material. var textureUsed = 'rock_1'; var texture =...
Read more >
ShaderMaterial – three.js docs
Their texture property must be used instead. Built in attributes and uniforms are passed to the shaders along with your code. If you...
Read more >
Custom shaders with Three.JS: Uniforms, textures and lighting
In this post, I'll show you how to setup a custom shader with a three.js geometry, pass it your own uniforms, bind a...
Read more >
Three.js and Shadertoy
It's important to recognize it's called ShaderTOY for a reason. ... Then we can load a texture like we covered here and assign...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found