KTX - SRGB texture export

Hello, I know this has been answered a couple of times before, but I’m still a bit confused about the correct export color format for textures from photoshop ( or other softwares )

As I understand texture used as data ( roughness map, normal map, metalness intensity map ) should be exported as linear while the albedo (color map) should be sRGB.

Is this conversation done internally inside THREE.js? or should I export from photoshop as sRGB or Linear?

We are also integrating the tool toktx into our pipeline and it has an option to convert images to srgb or linear, but using srgb with toktx causes the texture to be much darker so I’m wondering if I’m missing something

Correct!

Is this conversation done internally inside THREE.js? or should I export from photoshop as sRGB or Linear?

Both. :slight_smile:

For purposes of image file formats, sRGB provides an over-the-wire encoding1. Each R,G,B component in the image has limited precision. If you allocate equal precision for every color in the gamut, you need more precision (and larger files) than most image formats allow. sRGB includes a mapping (“transfer function”) that redistributes data so precision is focused on colors (generally darker areas) where human perception is better, meaning your images look better with less precision and smaller file size. When using the images within a rendering pipeline, we convert the data back to a linear encoding.

If the image doesn’t contain color data (like a normal map), all of that is moot, and you might as well allocate precision equally.

tl;dr — color images should be sRGB-encoded at export, and sRGB-decoded at import. three.js does this automatically as long as the texture is annotated with texture.encoding = THREE.sRGBEncoding.

We are also integrating the tool toktx into our pipeline and it has an option to convert images to srgb or linear, but using srgb with toktx causes the texture to be much darker so I’m wondering if I’m missing something

If you’re converting from JPEG or PNG to KTX2, the source files should already be sRGB. Otherwise it’s too late, the precision has already been lost. What you probably want is to use --assign_oetf srgb or --assign_oetf linear instead of --convert_oetf. Assigning just declares what the encoding is, it does not modify the data.


1 Aside: Technically I’m talking about the sRGB transfer function here. We use the sRGB white point (D65) and primaries (Rec 709) both over the wire and in the renderer.

1 Like

This implementation might be helpful as a reference —

thanks for the quick reply @donmccurdy!

I guess what happened then with the toktx tool was that it was converted to sRGB two times? making it look darker then it should?

Also, do you know if It’s possible to export and inspect the the linear/srgb from photoshop, or other image editing program?

with the two pictures below, one I exported with convert to sRGB and another without, they look pretty identical to me to be honest…

Should I export as sRGB from photoshop and then run --convert_oetf linear with toktx?

thanks!


Can you explain what you are really trying to do? Where are these textures coming from, and why are they being opened in Photoshop?

Very possible, yes.

Also, do you know if It’s possible to export and inspect the the linear/srgb from photoshop, or other image editing program?

Most programs’ defaults for PNG or JPEG would be sRGB. Whether Photoshop can export Linear-sRGB with these formats I don’t know, a lot of software does color management very poorly, and all your exports end up with an ICC Profile (embedded tag) saying they’re sRGB, even when they’re not. If Photoshop didn’t recognize that the original photo was already Linear-sRGB, then converting to Linear-sRGB at export might be wrong.

If you’re just opening and then saving a normal map in Photoshop it shouldn’t hurt anything with default settings, Photoshop should just write the same data it found, the ICC Profile was probably wrong to begin with, but the data won’t change. It’s really up to the original author of the original texture to get the data right.

Should I export as sRGB from photoshop and then run --convert_oetf linear with toktx?

If you need to use --convert_oetf, something is already very wrong. Avoid it entirely, unless you’re dealing with high-precision formats like EXR.

The rest 1000% depends on what you are trying to do. If we’re talking about color textures (.map, .emissiveMap) then you should use --assign_oetf srgb to tell toktx that the image is already sRGB.

If non-color textures, use --assign_oetf linear --assign_primaries none to tell toktx that the image is not sRGB encoded.

In either case, do not convert anything! The goal is to keep things in the same encoding throughout the pipeline.

great thank you for all the answer! it’s much clear now

We have a big project coming up and we are trying to sort out the overall pipeline between 3d artists, their export to our use inside threejs. Also how much and what we can automate

Since our artists use mostly Substance, the color space should be correct ( Color management | Substance 3D Painter Is color managed means sRGB )

thank you!

1 Like

Ok! Yes I think Substance Painter should do the right things here. :+1:

You’ll likely still need the --assign_oetf flags to make sure toktx does its part correctly as well.

1 Like