Closed kring closed 4 months ago
This PR fixes a bug reported on the forum: https://community.cesium.com/t/textures-appears-white-when-used-multiple-times-on-same-gltf/32278
Hey @kring , this link takes me to a page that says "Oops! That page doesn’t exist or is private.". Could you make it public? Or copy / paste the relevant instructions into this PR description?
this link takes me to a page that says "Oops! That page doesn’t exist or is private."
Oops, I didn't realize that was a direct message. You should have access to it now.
Merging this because it's approved and needed for today's release.
This builds on #1431 so merge that first.
This PR fixes a bug reported on the forum: https://community.cesium.com/t/textures-appears-white-when-used-multiple-times-on-same-gltf/32278
The model and instructions there make it easy to reproduce.
In this model, two primitives both reference the same material, and that material has a
baseColorTexture
. So when preparing the glTF for use with Unreal, and processing both of the primitives, we indirectly end up processing the same texture twice.The first time we process the texture, the associated image's
ImageCesium
has pixel data. So in a worker thread, we create a newFCesiumTextureResourceBase
(RHI texture resource) from it, and then clear the pixel data. So far so good.The next time we process the texture, we see that an
FCesiumTextureResourceBase
already exists for the associated Image, so we don't need to upload the pixel data again (which is good because we can't; the pixel data has been cleared). Instead, we create aFCesiumUseExistingTextureResource
referencing the existing RHI texture resources. Still all good so far.Next, in the game thread, we create a
UTexture2D
for each of the RHI textures previously created. They both refer to the same underlying data, which is no problem.Now here comes the problem. The way we manage the lifetime of
UTexture2D
instances is that we store them on the glTFTexture
object in a private extension. But in this scenario, we have twoUTexture2D
instances associated with a single glTFTexture
. The second one ends up replacing the first, and as a result the first is destroyed. We go through all the motions of creating the textures we need, but then we accidentally destroy one of them before we can use it.One way to fix this would be to make a single glTF able to reference multiple
UTexture2D
instances. But wait, why do we need twoUTexture2D
instances anyway? They were both created from the same glTF Texture, so they should be identical. They already share the same pixel data, but it would be better if they shared theUTexture2D
instances, too.So that's what this PR does. It adds the private extension to the glTF
Texture
earlier in the process, and uses it to store both theFCesiumTextureResourceBase
texture (during worker thread texture prep) and theUTexture2D
(during game thread texture prep). If the extension already exists, we don't need to process the texture again, we just need to use the existing reference counted texture resources.