i struggle with texture disposing for a while now… I tried it on my own with the documentation of three.js and r3f, unfortunatly i still have no working solution. For context, i’m building a configurator app where textures change alot. I implemented textures with different resolutions and also the case to handle hex input instead of textures. Here is a sandbox that makes it more clear:
Currently i tried to achieve the disposal with saving the previous selection of the user and use the useTexture.clear() Method to free the texture. For my understanding i also have to dispose the texture now but how? Also if you would implement this function differently i’m open for improvement suggestions.
first of all, hooks can’t be conditional. a component must return the exact order of hooks every time, there can’t be any if then else including or excluding hooks conditionally.
as for useTexture, that hook is made to cache textures, so that they are re-usable throughout the app. this is likely not what you want. you can of course clear them from the cache, but this doesn’t dispose them, you dispose it via texture.dispose().
i would suggest you just use vanilla textures whose lifecycle you track yourself, you don’t need a cache if you don’t re-use, and working with a cache that you invalidate all the time is pointless.
Thanks for the informative answer, i changed my code to match yours and it works with textures. Problem is when i only want a color without a texture the last selected texture stays on the object. Do i have to dispose it from the mesh aswell?
Okay i changed it to this code, now textures and hex values are supported:
Is this the way you would implement this feature? The CubeTexture Component in my Project is getting used in alot of other components so i want it to work as good as it gets:)
Edit: I tested switching textures and it doesnt seem that the texture has to be loaded again is it really disposing?
TürenStore((state) => state.AFLG) is a bit weird. all hooks start with “use”, this would be flagged by a linter. a white texture is a good idea btw because you can’t go from a texture to no texture in threejs, you would have to re-compile the material. as for hook dependencies, they’re supposed to indicate when a hook should run, if you throw something like ./textures/${AFLG}/${texture}.jpg in the dependencies array, and then use it again in the function it would bloat the bundle, the full string as a dep is unnecessary.
The following properties can't be easily changed at runtime
(once the material is rendered at least once):
numbers and types of uniforms
presence or not of
texture
fog
vertex colors
morphing
shadow map
alpha test
i’ve tried it as well and it seems to behave like the docs say. i don’t know about the codepen, perhaps it’s re-creating the materials somehow.
tried it out quickly festive-smoke-sjrtdy - CodeSandbox just changing it to null has no affect. im logging the material out and map is null, texture stays present nonetheless.
very curious. i tried with a vanilla example doing the same, click it map goes to null, texture remains. Threejs basic example (forked) - CodeSandbox maybe the codepen is tripping something else up. the reason why you can’t remove a texture without re-compile is that the texture is uploaded to the gpu only once, this happens in gl.initTexture.
Wild, no idea what that’s about, the pen is doing the same, loading model and texture, assigning the texture to map of material, initializing the scene, rendering and then adding an event listener for the button… This has always worked with runtime js for me as I say, maybe bundler is latching / caching the material map somehow?