How to switch out texture images on click using ImageUtils

I want to change the texture image on the click of a button. I had this working with the TextureLoader() object, but since my version of Internet Explorer 11 doesn’t support that, I have to use the deprecated ImageUtils.loadTexture way. This is what I have so far, inside my Init() function:

//paths to each of the texture images.
var earthNoCloudsTex = basePath + 'Content/images/earth_no_clouds_12k.jpg';
var earthDarkTex = basePath + 'Content/images/earth_dark_12k.jpg';
var earthDarkInvertTex = basePath + 'Content/images/earth_dark_invert_12k.jpg';
var earthRedTex = basePath + 'Content/images/earth_dark_red_12k.jpg';

// Flag for current texture that is displaying
var currentTexture = earthNoCloudsTex;

var earthSphere = new THREE.SphereGeometry(EARTH_RADIUS, EARTH_SEGMENTS, EARTH_RADIUS);
var earthMaterial = new THREE.MeshPhongMaterial({
    map: new THREE.ImageUtils.loadTexture(basePath + 'Content/images/earth_no_clouds_12k.jpg')
});

var theEarth = new THREE.Mesh(earthSphere, earthMaterial);
scene.add(theEarth);

//Add toggle click event for changing earth background texture
$('.texture_change_button').on("click", function (e) {
    //figure out which button was clicked
    var buttonClicked = $(this).attr('id');
    //disable all currently disabled buttons before disabling another
    $(":disabled").attr('disabled', false);
    //disable button clicked so that it can't be clicked twice.
    $(this).attr('disabled', true);
    //depending on the id of the buttonClicked, update the currentTexture
    switch (buttonClicked) {
        case 'earth_no_clouds_button':
            currentTexture = earthNoCloudsTex;
            break;
        case 'earth_dark_button':
            currentTexture = earthDarkTex;
            break;
        case 'earth_dark_invert_button':
            currentTexture = earthDarkInvertTex;
            break;
        case 'earth_red_button':
            currentTexture = earthRedTex;
    }
    //switch out the image with new currentTexture
    earthMaterial.map = THREE.ImageUtils.loadTexture(basePath + currentTexture);
    earthMaterial.needsUpdate = true;
    scene.add(theEarth);
});

Update: when i click the button, it removes the texture image, but never adds the new one… so i just see a black sphere.

I don’t understand why IE 11 does not support TextureLoader. Can you please explain in more detail why this is a problem? Besides, what version of three.js are you using right now?

I believe it is version 89. Will check when i get to work. Honestly I don’t know why but TextureLoader would never render. Deprecated version does :man_shrugging:

We are using Three JS Version 97, IE 11.1039.17763.0

And sadly for things around here, getting a newer version approved would take a while, so I want a temporary solution until then.

Any idea what I am doing wrong? I mean it is possible to switch the textures out via deprecated loadTexture() right? Thought I was doing what everyone else has been… just isn’t showing the new image. I will debug some more.

Consider to share a live example that demonstrates the issue.

THREE.ImageUtils.loadTexture() was already deprecated in R97 and internally used TextureLoader. The implementation looks like so:

ImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {

	console.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );

	var loader = new TextureLoader();
	loader.setCrossOrigin( this.crossOrigin );

	var texture = loader.load( url, onLoad, undefined, onError );

	if ( mapping ) texture.mapping = mapping;

	return texture;

};

That’s why I’m so confused when you say you can’t use TextureLoader. Because indirectly, you already use it.

hmmm… well as soon as i changed to use that everything worked in IE 11… I also was using THREE.Group()… Maybe that is what caused it to not render in IE11? Instead of adding everything to a group, then adding to scene, i just add straight to the scene… I will try using the new TextureLoader() directly again, Idk all of this is weird and I just hate IE. lol

I can’t image that this is the root cause for your issue…

Honestly I think it is something with our .NET MVC project not playing well with THREE JS, because it renders outside of .NET MVC project just fine in IE11. Sharing a live example wouldn’t help, because it would work for you all in your own environment.

I’m cool with using the code I have now, because for some reason, it is working in all browsers. I am just trying to figure out why changing the texture image on click is not working.

Um, can you check if the MIME type of loaded textures is correct? Maybe they are not served in the correct way…

Ok so you are on to something! I didn’t know that Internet Explorer would change the mime type… But sure enough, the mime type is text/html, and I get a 401 unauthorized… This is definitely the issue… although no idea why it is unauthorized or text/html… In chrome everything is fine. Here is IE 11 dev tools:

UPDATE: I guess I have to figure out the 401 unauthorized thing… although I still have no idea why the deprecated texture loader works. I have cleared cache and everything in IE11, and it still works.

The code with up to date TextureLoader():

//for loading earth texture images.
var loader = new THREE.TextureLoader();

// Instantiate material to later be wrapped around the sphere.
var material = new THREE.MeshBasicMaterial();
// Create the sphere
var sphere = new THREE.SphereGeometry(EARTH_RADIUS, EARTH_SEGMENTS, EARTH_RINGS);
// Instantiate mesh to later combine sphere with material
var mesh;

loader.load(currentTexture, function (texture) {
    // Map the texture to the material. 
    material = new THREE.MeshBasicMaterial({
        map: texture
    });
    // Create a new mesh with sphere geometry.
    mesh = new THREE.Mesh(sphere, material);
    // Add mesh to globe
    earth.add(mesh);
});

It seems you are running the tests on local host.
Have you tested it online?
Have you tested it locally without virtual host?
How does 3JS texture examples work for you?

Can you use absolute URL instead of relative for textures in your test?

I have tested it on a live server, yes. Same thing.

The examples don’t render at all here in our version of IE 11: https://threejs.org/examples/#webgl_depth_texture

I will try an absolute URL to see what happens.

I’m sorry, I meant the example section on your version of 3JS. Since 105, the example sections are not accessible to browsers that don’t support modules.

So for now, I think I am moving on, since our sprint cycle ends today and I am now tasked with working on new stuff… I am just going to continue using the deprecated version for loading textures, it works locally and on live server. I got the switching of image textures working using (Technically the topic of this thread):

    //switch out the image with new currentTexture
    earthMaterial.map = THREE.ImageUtils.loadTexture(currentTexture);
    theEarth.material.needsUpdate = true;
    scene.add(theEarth);

The IE11 thing seems to be something specific to our .NET MVC project and not Three JS (Could be related to our Content/Images/ folder permissions, although every other browser seems not to have an issue… :expressionless:). I will come back and figure that out, but for now, I think this thread can be closed. Thank you all for pointing me in the right direction with the IE11 MIME Type/unauthorized issue. I will definitely look into this whenever I have the time again, and will post another thread or something to let people know.

Thanks again!

Feel free to post in this topic. We are not closing them like at github.

1 Like