2
votes

I have a ThreeJS scene and I'd like to provide the option of seeing all models in different modes (with or without textures and/or wireframe).

I'm trying to accomplish this using only one Geometry and one Material for each object.

When I try to remove the texture of an object by setting the map property of its material to null something bizarre happens. The object takes the latest loaded texture, even if it was loaded and applied to another object. Is this somehow an expected behavior? If not, how should I remove the map?

1
Do you have a fiddle of the issue? See github.com/mrdoob/three.js/wiki/Updates which suggests making sure material.needsUpdate is true. Note the especially lengthy section on materials, as well as the warning about modifying a shader program. I would make a template material that is cloned and the texture map then added to it. On removal of the map, just clone a new material instance and don't map it. Since you haven't shared any code it's difficult to say why your map is defaulting to another image. Grabbing image data from a recent buffer seems unlikely and a little scary?Radio
needsUpdate does the trick but yes, grabbing an image from a recent buffer seems wrong. Opened issue just in case github.com/mrdoob/three.js/issues/8903Craveiro
I have seen a similar texture ram issue in openGL lead to some embarrassing moments for some users in the SecondLife platform ages ago. Users were creating meshes (prims), adding and removing textures from their local machines, which would sometimes send private image data to the other users instead of the proper material. It's probably wise to get it documented if it's happening here.Radio

1 Answers

0
votes

a good approach would be to initialize the materials you will need from the beginning :

var materials = {};

materials['lambert'] = new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading }  ); 
materials['phong'] = new THREE.MeshPhongMaterial( { color: 0xFF0000, specular: 0x009900, shininess: 30, shading: THREE.FlatShading }   ); 
materials['basic'] = new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending }  ); 
materials['wireframe'] = new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe : true  }  );

and replace the material of your object when you need to :

function changeMaterial(id){
    mesh.material = materials[id];
} 

changeMaterial('wireframe');

I did a fiddle that demonstrates that : http://jsfiddle.net/95t964o0/75/

I did not use a material with a texture because it's a bit tricky for jsfiddle.com to load an image.

Note : be carefull when many objects share the same material! If you make changes to the material of an object it affects all the others (obviously because it is shared).