KhronosGroup / glTF

glTF – Runtime 3D Asset Delivery
Other
7.2k stars 1.14k forks source link

Semantic of metallicRoughnessTexture with 1 channel? #2298

Open Caenorst opened 1 year ago

Caenorst commented 1 year ago

Hi team!

I'm trying to extract some data from the objaverse dataset, seems that some of those models contains a metallicRoughnessTexture with a single channel.

The specs says:

The metallic-roughness texture. The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. These values MUST be encoded with a linear transfer function. If other channels are present (R or A), they MUST be ignored for metallic-roughness calculations. When undefined, the texture MUST be sampled as having 1.0 in G and B components.

But doesn't seems to acknowledge that single channel texture could exist. However I tried few viewer and tools that can load GLTF and everything seems to work just fine.

What is the expected behavior on this case?

Thanks!

lexaknyazev commented 1 year ago

The base glTF 2.0 spec supports only PNG and JPEG textures. In these formats, single channel data is interpreted as grayscale, i.e., R, G, and B components have the same value.

emackey commented 3 months ago

Spec clarification desired: single channel is grayscale (R, G, B from the single channel), and additionally, a 2-channel image represents gray + alpha (and so the first channel decodes to RGB and the second channel to alpha). We talked about this in the PBR TSG today and agreed there should be sample model(s) to test this. A clarification in the glTF specification explaining this would be helpful to implementers, but ultimately it's up to individual image formats to clearly state the intention of specific encoded channels within an encoded image. glTF itself does not have direct access to channels in the encoded image, only the fully decoded / expanded channels.

MarkCallow commented 3 months ago

Spec clarification desired:

Is a similar clarification needed for KHR_texture_basisu?

The metalness values are sampled from the B channel. The roughness values are sampled from the G channel. These values MUST be encoded with a linear transfer function. If other channels are present (R or A), they MUST be ignored for metallic-roughness calculations

This does not play well with block-compressed GPU textures. If you have 2 independent channels, as metallness and roughness appear to be, you want one in the RGB components and 1 in the alpha component for least compression artifacts.

emackey commented 3 months ago

It would be interesting to have some kind of swizzle-decode operation available for basisu, along the lines of "channel 0 decodes to green, channel 1 decodes to blue" or similar. We've established that the core spec wording quoted above would not need to change because glTF is sampling from the fully decoded RGBA channels. Perhaps some new extension could provide information on which basisu channels decode to which glTF color channels within a texture?

lexaknyazev commented 3 months ago

Is a similar clarification needed for KHR_texture_basisu?

No. The recommendation is to prefer UASTC over ETS1S for ORM textures; the former provides enough quality to not worry much about cross-channel artifacts.

Perhaps some new extension could provide information on which basisu channels decode to which glTF color channels within a texture?

This is theoretically possible but would cause major fragmentation issues.

emackey commented 3 months ago

Perhaps some new extension could provide information on which basisu channels decode to which glTF color channels within a texture?

This is theoretically possible but would cause major fragmentation issues.

Good point

MarkCallow commented 3 months ago

No. The recommendation is to prefer UASTC over ETS1S for ORM textures; the former provides enough quality to not worry much about cross-channel artifacts.

Okay. Indeed the ASTC spec only uses "may":

"For blocks which have uncorrelated channels — for example an image with a transparency mask, or an image used as a normal map — it may be necessary to specify two weights for each texel"

BoyBaykiller commented 2 months ago

This does not play well with block-compressed GPU textures. If you have 2 independent channels, as metallness and roughness appear to be, you want one in the RGB components and 1 in the alpha component for least compression artifacts.

Some peeps from the Graphics Programming server are also not happy with that. It means we can't use BC5 which is two uncorelated channels and a perfect fit for metallicRoughness texture. I've written IDK_BC5_normal_metallicRoughness for personal use because of that.