copyTextureToTexture makes textures dark until camera is zoomed in

Hi All, I’m getting started with copyTextureToTexture in a scene that loads lots of images and paints each to a shared texture.

What’s odd, though, is that after the textures are copied, the relevant region of the updated texture appears quite dark until the camera is close to the sprite that displays that texture. E.g. in the scene below, you can see that the texture is quite dark until the camera gets close to the cell:

out

Does anyone know what might be causing this? I’m using rawshadermaterial but there’s nothing fancy going on in there–just fetching the texture from a uniform atlas. I was previously updating a canvas and passing that as the uniform to the scene and this dark shading problem wasn’t happening–it only started when I switched from the canvas updating method to copyTextureToTexture.

Any suggestions others can offer would be hugely appreciated!

The image does not show.

Maybe this is a strange question, but are you sure the texture block looks good once you have zoomed in? Dimness issues could be related to gamma correction etc., but I wouldn’t expect to see different results on different ranges…

A-ha! How about mipmaps? If the filtering interpolates between the full-resolution image and the next mip level, which is at the time not updated with a downscaled version of the new texture block…

1 Like

Yes, the texture looks as expected when I’m zoomed in. The texture is just displaying a little image that’s 128px in one dimension (either height or width) and <= 128px in the other dimension, and right now those little thumbs are a little grainy in the actual jpg file that’s loaded, so the texture looks as expected when the camera is zoomed in.

The mipmap idea is interesting–I see how this could muck things up. Is it possible to disable the use of mipmaps altogether? I tried setting:

// cell is an object with a canvas context
cell.ctx.drawImage(img, 0, 0);
//this.cell.texture.generateMipmaps = false;
//this.cell.texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
cell.texture.minFilter = THREE.LinearFilter;
cell.texture.magFilter = THREE.LinearFilter;
cell.texture.needsUpdate = true;
// pass the data from the cell texture to the lod texture
renderer.copyTextureToTexture(coords, cell.texture, tex.texture);

I’m still seeing the strange darkness though. Is there another line of investigation I can try?

1 Like

What if you do:

cell.texture.minFilter = THREE.LinearFilter;
cell.texture.magFilter = THREE.LinearFilter;
cell.texture.needsUpdate = true;
// pass the data from the cell texture to the lod texture
setTimeout(()=>renderer.copyTextureToTexture(coords, cell.texture, tex.texture), 500);

I am asking because I think the copy will be done before the texture update otherwise. If renderer.copyTextureToTexture does not check texture.needsUpdate and update the texture before copying, you will probably have the same problem with your code above, but possibly not with the timeout version. This would be an issue with renderer.copyTextureToTexture, and should probably be reported. I don’t have time to check the source code now.

It calls textures.setTexture2D on the destination texture, which internally checks texture version (needsUpdate). Hmm, so no luck on that either, I think… :thinking: Please don’t assume that’s the end of the story! (I mean, it may still be worthwhile to pursue the timeout test, just in case. And definitely the mipmap lead.)

2 Likes

The plot thickens! I’ll keep poking about…

1 Like

Based on @Mugen87’s successful partial texture updates with data textures [example] I’m thinking this may have something to do with mipmap handling in copyTextureToTtexture (discussed in https://github.com/mrdoob/three.js/issues/14423…)

1 Like

Sorry for jumping in lately^^. But yes, you’ve picked the correct issue! It’s definitely related to mipmapping.

2 Likes