Update just one channel of texture

If I wanted to update just one channel of a texture, say because it is an ORM texture and I just want to update the metalness part of the texture, what would be the best approach?

I could use DynamicTexture, but as I am targeting iOS I am concerned about the amount of memory that will be used.

Alternatively I could use readpixels → apply my changes to a single channel → update the texture somehow (maybe using the updateTextureData method?)

Before I started trying random things I was hoping someone may be able to point me in a recommended direction?


Yes, I think using readpixels to get the data once, change the channel you want and use updateTextureData to update the texture is a good way to do it.

1 Like

Hi @Evgeni_Popov - I am struggling to get this to work, seeing the error:

[.WebGL-00004DE800B40D00] GL_INVALID_OPERATION: Invalid combination of format, type and internalFormat.

I have recreated the issue on the following playground by simply reading the pixels of a loaded texture and then attempting to write them back to it:

Any chance you could help? Thanks

For some reasons it does not work with a .jpg file, but it works with a .png…


grass.png is a 512x512 image, so the buffer is 1048576 bytes and it works as expected (I add some randomly colored pixels before updating the texture, to easily see if the update works).

Now, using fire.jpg instead:

This is also a 512x512 texture, so buffer is also 1048576 but this time it does not work.

However, I checked that the webgl texSubImage2D call uses the exact same parameters in both cases!

So, I don’t understand why it does not work (note that it works in WebGPU)…

I have to call @sebavan to the rescue!

@Evgeni_Popov - it looks like the issue is that jpg textures are incorrectly thought to be RGBA by babylon when in fact they are RGB.
Forcing the texture type and format for both the texture and Internal texture allows the code to run.

However, as the read pixels are RGBA and we are writing to RGB additional work needs to be done to ensure the data written to the texture are the actual values required.

An example playground with the RGB fix (though without the correct RGBA to RGB pixel conversion) is here: https://playground.babylonjs.com/#KBS9I5#33305

This does mean there is a bug in which the format and type for a jpg file are not being set correctly by the engine when the texture is loaded.

You’re right, here’s a PR that will set the correct texture format and type at load time:

Regarding readPixels, however, we can’t do anything, WebGL1/2 only supports reading into RGBA buffers…