KTX texture problem

It is not. I am compressing the .jpg images with this command:

toktx --bcmp skybox_pz-etc1.ktx skybox_pz.jpeg

(Khronos Texture Tools: toktx)

since --bcmp uses ETC1S / BasisLZ and implies --t2, I figured adding the -etc1.ktx would make sense. I also tried using ktx2 instead of ktx, but that did not work either. I printed out the result from const formatUsed = engine.setTextureFormatToUse(available); and it is always -dtx.ktx, which makes no sense to me, as it shouldn’t be compressing using DirectX.

I tried just putting the assets in the local project directory and referencing the address to the assets folder but that resulted in the same thing.

There is a bit of confusion here. There are two different versions of KTX: 1 and 2. KTX version 1 only supported platform specific formats. KTX version 2 supports Basis Universal which can transcode into platform specific formats at runtime.

The KTX1 loader allows you to specify multiple suffixes to allow you to provide each individual platform formats. You cannot use KTX2 files with this method.

KTX2 supports cubemaps, but we don’t have support for them in Babylon yet.

TLDR: Use KTX1 for this scenario for now. You’ll need a separate KTX1 (.ktx) file for each format (astc, dxt, pvrtc, etc2, etc1) for each face of the cubemap. I’m not exactly sure how to generate these files though. I don’t believe toktx is the tool to generate KTX1 files.

1 Like

Thank you for clarifying this. It seems that PVRTexTool should work for this purpose, correct?

Since “The texture must be encoded with the Y-axis flipped”, would I toggle on InvertZ on the cube texture (seems to be the only option for CubeTexture…no InvertY) after the new CubeTexture constructor is called?

1 Like

I’m not sure about the InvertY issue. Try it out and find out? :slight_smile:

So I’m still having an issue even just getting the cubeTexture to retrieve the textures properly. I thought I resolved it, because it showed up a couple times, but turns out it wasn’t using the ktx textures like I thought it was.

I am using the PVRTexTool GUI as suggested in this babylon doc:

Using the texture encoding process here
https://docs.imgtec.com/oxy_ex-2/UtilitiesSrc/PVRTexTool/Documentation/PVRTexTool_Manual/topics/PVRTexTool%20GUI/pvrtextool_texture_encoding.html

I am using these skybox images (512p x 512p):
https://playground.babylonjs.com/textures/skybox_nz.jpg
https://playground.babylonjs.com/textures/skybox_ny.jpg
https://playground.babylonjs.com/textures/skybox_nx.jpg
https://playground.babylonjs.com/textures/skybox_pz.jpg
https://playground.babylonjs.com/textures/skybox_py.jpg
https://playground.babylonjs.com/textures/skybox_px.jpg

and this encoding type
Screen Shot 2021-06-04 at 1.45.05 PM
with ETC Encoding Mode: Fast
The Generate MIPMaps and Vertical Flip checkboxes are checked, as suggested in this babylon doc as well:

I am using the skybox_nz-etc2.ktx, skybox_ny-etc2.ktx, … naming convention for my compressed files.

I am saving the compressed jpegs outputted from the encoding tool to .ktx extension files.

Additionally, I am not sure why PVRTexTool is outputting LARGER files than the jpegs, as seen here:
Screen Shot 2021-06-04 at 1.50.41 PM
The pattern of larger outputted files was consistent across all encoding types when saved as .ktx.
The only times the encoded files were not larger when saved was when they were saved as .pvr files, but it seems that the CubeTexture function only takes ktx, correct?

And, as a side note, there doesn’t seem to be a way to utilize the CubeTexture function to create a CubeTexture out of a single cube texture file (like an image file that contains all of the skybox images in their proper unfolded positions), correct?
Any thoughts as to why?

I tried many other permutations of encoding types to no avail. Would you mind trying to reproduce this? Feel free to point the textures retrieval address to something else.

Thanks!

I’ve never heard of .pvr files. If the encoding for the KTX is some kind of block compression, it will most likely be bigger than JPG. The main benefit is how much GPU memory is used. JPG will expand to full raw resolution on the GPU.

There aren’t that many file formats that can contain a cube texture. DDS can but it’s not portable. KTX version 2 can, but we don’t support it yet. If you are using this for an environment, there is the .env format which is a single file.

I am not using the CubeTexture as the env. I am using it as the skybox. It seems that the CubeTexture function only looks for -dtx.ktx files when putting together the skybox. Why is this? I am on a macOS and it seems that this playground here:
https://playground.babylonjs.com/#1SCH7H#5

has only tested dtx on macOS, and not any other compression on macOS, which contradicts the suggestions laid out in this documentation:

which says that some formats should work on multiple platforms.

Additionally, it would help greatly if you or someone else could reproduce this issue given the outline that I provided above. If the PVRTexTool is not your recommended tool for compressing textures, then please point me in the right direction. Otherwise, it is the main one suggested in that documentation (besides encoding basis from the source repo) and thus the one I am trying to utilize for this issue. I’ve tried all the encoding types (correctly, to my knowledge) to create each file extension above. None of them work with ‘new CubeTexture()’ constructor, nor CubeTexture.createFromImages().

Based on other forum posts, it seems this is either a known issue and hasn’t been resolved or that something is busted behind the scenes.

The env format can be used as a skybox as well as IBL. This is how the sandbox does it. This format is not compressed on the GPU though.

The selection is based on the capabilities reported by the browser. The code iterates through the array passed to setTextureFormatToUse and tries them in order. I tried this on my mac and the texture loaded which is good, no?

I’m not exactly sure which issue you refer to. If you are talking about trying to load images into a cube texture, can provide a playground link of the issue?

Thanks for the timely response.
In terms of reproducing the issue, I mean encoding the compressions of babylon’s given skybox jpgs into ktx or whatnot via PVRTexTool and getting those compressed images to load in when creating a new skybox.

This is my playground:
https://playground.babylonjs.com/#UHQ4FB#2

The textures and encoding strategy I am using are shown previously in this thread.

The point of the issue:
Right now the skybox alone is seemingly causing 200MB of memory usage in our app. We want to shrink that as much as possible, so we are compressing the textures.

I tried various compression encodings in the PVRTexTool GUI, to no avail. They load without error, but they do not render in the scene.
I followed the suggestions outlined here:

and then here:

but it seems the playgrounds on those posts are dead ends.

So I’m wondering if there is a compatibility issue, if this is an issue on the Babylon side, or if I am encoding them incorrectly. Thanks!

This is good, but the texture loaded is not being utilized in a skybox, which is not the point. The compressed textures that are being imported are not working with Babylon’s cube texture functions

After debugging a bit, it looks like the KTX texture loader doesn’t support loading 6 separate files as a cubemap. The code seems to indicate there is cubemap support, but it’s not through 6 separate images. I didn’t write this code, so I’m trying to decipher what it is supposed to be. I think it wants a single KTX that has 6 faces encoded in the file. I’m not sure how to generate a file like this.

It looks like there are ways to do this with PVRTexTool (imgtec.com) (see page 21).

1 Like

Thanks for checking on that @bghgary. So I can make a cubemap via PVRTexTool for sure. But which function would I then utilize with this cubemap texture?

It seems the CubeTexture() constructor does indeed take in a source url and then automatically appends the px,py,pz,nx,ny,nz extensions to make 6 separate calls to where the textures are. This works fine with jpgs but not ktx files.

Additionally, when I try to use a single cubemap texture -dxt.ktx file and then fall back to the 6 individual jpgs if that does not work, like @Vinc3r did above, that does not work either. I am wondering if they got theirs to work. I have that setup in my current playground here:
https://playground.babylonjs.com/#UHQ4FB#5

and here are my files in S3:

The CubeTexture.CreateFromImages() function also seems to only take in 6 texture images.

What function would I use for a single cubemap-format -dxt.ktx compressed texture image? Or basis image?

I tried using CubeTexture.CreateFromPrefilteredData(cubeTextureUrl, scene, null, false);

(as seen in this playground):

https://playground.babylonjs.com/#UHQ4FB#3

with a cubemap-format (dds) texture. This seems to have the most promise, but the image is decoded/transcoded in a really funky way. I think that might be related to the issues outlined here:
Basis support for skyboxes? - #9 by bghgary even though I am not using Basis.

I’m currently using the cubemap texture from here:

https://swivel-api-dev.s3.amazonaws.com/skybox_textures/combined/skyboxConvertedCubeMap.dds

Should I not have exported the cubemap into dds format for the CreateFromPrefilteredData function? Which format makes the most sense to maintain as much compression as possible and still work?

I thought only dds/env are compatible to hold a cubemap-format texture.
Or maybe Basis too, but the issues in the forum post I just posted above in this reply don’t seem to be resolved either.

Thanks!

Let’s just focus on one thing at a time. I say start with KTX. I can see there is code trying to load a single KTX with 6 faces in them, but the code currently blocks this from happening. Once I unblock it, the code seems to be trying to load a KTX and is expecting 6 faces. Do you have a KTX file with 6 faces I can try?

Here’s a cubemap-format ktx texture that should have all 6 faces in it:
https://swivel-api-dev.s3.amazonaws.com/skybox_textures/combinedTest/skybox-dxt.ktx

1 Like

The KTX loader claims that this file only has 1 face. :frowning:

That’s what I noticed too. That seems to have been the root of the issue. Thank you so much for your patience and helping my finally realize the error of my process!

The original file I was using looks like:


which is standard cubemap format, which mislead me to believe that it was encoded correctly as a cubemap and not as a single image.

This is what went wrong:
At first I converted the 6 jpgs into a cubemap jpg and then compressed that cubemap jpg into ktx.

Now, I just created a cubemap natively in PVRTexTool and then compressed it with DirectX11 BC1 (-dxt.ktx) and got this:
https://swivel-api-dev.s3.amazonaws.com/skybox_textures/combinedTest/skybox-dxt.ktx

which (thankfully!!!) shows up here:
https://playground.babylonjs.com/#UHQ4FB#7
The only issue with that version is that the sides are flipped. I compressed it in PVRTexTool with the vertical flipped flag turned on (as suggested in the documentation).

When I compressed it instead with vertical flipped flag turned off, it shows up correctly!:
https://playground.babylonjs.com/#UHQ4FB#8

Lastly:
In this version of skybox creation (using CubeTexture.createFromPrefilteredData), seams can be seen where the images are stitched together. I noticed that, when using the new CubeTexture() constructor, the image seams are not really noticeable (back when I was testing which function to use with the separate, uncompressed jpgs). Is there a way to mitigate this? Or is this a byproduct of having to use CubeTexture.createFromPrefilteredData?

Thanks!

Nice. Glad this finally works. There is still an issue with the code though. You shouldn’t have to pass https://swivel-api-dev.s3.amazonaws.com/skybox_textures/combinedTest/skybox-dxt.ktx directly. You should be able to pass https://swivel-api-dev.s3.amazonaws.com/skybox_textures/combinedTest/skybox.ktx and use the texture selector, but there is code blocking this from happening right now. If you can file an issue on GitHub, I can submit a fix for it.

createFromPrefilteredData just calls the constructor with some flags, so there will be no difference for the seams. I’m not sure why there are seams. Perhaps it’s from the compression or maybe there is a bug somewhere.

1 Like