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

[v9] Texture gets overwritten instead of swapped out on prop change. #3432

Closed
roelkok opened this issue Jan 18, 2025 · 3 comments
Closed

[v9] Texture gets overwritten instead of swapped out on prop change. #3432

roelkok opened this issue Jan 18, 2025 · 3 comments
Labels
bug Something isn't working

Comments

@roelkok
Copy link

roelkok commented Jan 18, 2025

I'm using v9 and I ran into an issue were a texture that I was using kept being overwritten.

Let's say I have 3 textures A, B, and C and a component with a MeshBasicMaterial. When I pass texture A to the map prop of the material, then later on B and finally C, my component seems to render the updates fine. However when I pass texture A again, I see no update.

function MyComponent({ myTexture }) {
  return <mesh>
    <planeGeometry args={[2, 2]} />
    <meshBasicMaterial map={myTexture} />
  </mesh>
}

I realized that the material kept using the same texture (A) but that the contents of it kept being overwritten with the other textures. So when using texture A again after C no change was visible because its contents were overwritten by C.

I created a pull request that doesn't copy a new texture into an existing one on a instance on prop change by checking the UUID. It fixes the issue in my case, but not sure if this is the right approach.

@drcmda
Copy link
Member

drcmda commented Jan 19, 2025

thanks! this is really interesting! you are 100% right that this is bugged or wrong behaviour, just nobody stepped into it yet.

this is what happens currently:

  • map={a}, because map is originally NULL fiber will mutate material.map = a 👍
  • map={b}, which in fiber translates to material.map.copy(b) because both target & value constructors now match and have .copy(), the texture gets overwritten with B, so A is destroyed 😬
  • map={a}, which is material.map(a), it copies itself and will still show texture B 🫣

the problem is that it has destroyed the A texture, the app can never go back to that

the correct behaviour would imo be,

  • map = a because map is NULL 👍
  • map = b, bc it originally used to be NULL, we must assume an external object that we shouldn't mutate directly 👍
  • map = a, bc it originally used to be NULL, same as above 👍

it would now show texture A

we can probably detect if something was originally NULL ... we do something similar in the diffProps function, fiber maintains a collection of default/original values. this could tap into that and check.

@RektTillNoon
Copy link

nice catch!

@roelkok
Copy link
Author

roelkok commented Jan 22, 2025

I can confirm the fix in rc5 works for me.

@CodyJasonBennett CodyJasonBennett added the bug Something isn't working label Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants