Constructing a texture from WebGLTexture

Hi,

I’ve got a WebGLTexture which I would like to use in constructing a texture. There doesn’t seem to be any way to construct a new texture just from a WebGLTexture/matrix reference ( Using raw textures is unfortionatly out of the question ). I’ve attempted to manually override an existing texture’s underlying _webGLTexture, to no success:
texture._texture._webGLTexture = myWebGLTexture;

Any help would be much appreciated.

Hello and welcome!

I suppose you may use this information - Dynamic Textures | Babylon.js Documentation

Thanks @labris ,

Unfortunately, unless I’m missing something, dynamic textures don’t solve my problem.

Essentially, I have a BABYLON.Layer with isBackground enabled. I need to set it’s underling WebGLTexture to my own (specifically to a WebGLTexture that I have ).

You are not supposed to handle low level gl objects yourself, as doing it in parallel with Babylon will likely generates some problems… Maybe you can read the pixel data from this texture and create a proper Babylon texture from this?

Reading the pixel data and generating a Babylon texture is something that would impact performance too much in this use case as the texture updates every frame in an application that’s very performance dependant (hence going the low-level route).

I understand that updating internal gl texture would be considered ‘hacky’, but it seems to be the most performant way forward.

Are you using Babylon 4.2 or 5.0? In 5.0, _webGLTexture does not exist anymore, you must use _hardwareTexture._webGLTexture instead.

I’m on 4.2.

I’ve set up a minimal example of what I’m after.

https://playground.babylonjs.com/#YEHTQ5

(I only have WebGLTexture + it’s matrix to work with, so just overriding the whole ‘texture’ is unfortunately not something I can do)

In this playground, I have two materials - One on the ground plane, of a smiling face, and another, for the background layer - an image of a lake.

I’m attempting to set the background image to the one of the ground, via _webGLTexture, but that does not seem to work.

1 Like

It does work if you choose 4.2 as the version of the PG (click on the version to change it):
image

1 Like

Hey @Evgeni_Popov ,

The result should be setting both textures to an image of a smiley face, not the lake

Ok, so you will need to create a new InternalTexture as there are some caching mechanisms based on InternalTexture:

https://playground.babylonjs.com/#YEHTQ5#6

Of course, we are not responsible for any damage your computer may suffer because of this :wink:

1 Like

Seems that the last example works with 5.0 as well :slight_smile:

Ok, that should not work in 5.0, and it turns out that my solution does not work even in 4.2, it is in fact using the same InternalTexture than the ground instead of replacing _webGLTexture of the background… Will have another look tomorrow.

2 Likes

So, your solution does work but for some reason you need to let the system be ready before doing the texture update:

https://playground.babylonjs.com/#YEHTQ5#7

And for 5.0:

https://playground.babylonjs.com/#YEHTQ5#8

2 Likes

Oooh! That’s a good find. Thank you for your help @Evgeni_Popov, much appreciated! I will give this a shot today :slight_smile:

Edit (21/04/2022) for anyone reading in the future:

There’s now a new api which makes this a little less hacky!
Babylon.js/packages/dev/core/src/Engines/engine.ts at a578406f39b34a26c983d0006e2c22fef69501da · BabylonJS/Babylon.js · GitHub

2 Likes

Would it be a good idea to add public methods or attributes to access WebGLTexture instances (or WebGPU ones)?

What would be the goal?

We tend to hide the internal data to protect our capability to update without breaking backward compat.

That being said, in that case you can still call groundMaterial.diffuseTexture.getInternalTexture() to get access to internal data if you REALLY want to :wink:

Also since 3 years when the post was made we added: wrapWebGLTexture and wrapWebGPUTexture to consume external textures.

4 Likes

Hi @Deltakosh In my case I want to retrieve the internal WebGLTexture from BABYLON.Texture, in order to use that texture with CesiumJS or other native WebGL apps.

By now I am using Texture.getInternalTexture()._hardwareTexture._webGLTexture to achieve this, so I wonder whether it’s possible to offer some public methods.

Thank you @sebavan, I am also using engine.wrapWebGLTexture() somewhere else for the inverse operation XD

You could do Texture.getInternalTexture()._hardwareTexture.underlyingResource, which accesses a single hidden property instead of two.

1 Like