i am looking at a problem, where i have to swizzle the channels of a Texture (or Texture2D). Texture is loaded dynamically from the web. It is a GLTF ORM Map and i need to convert it so the LIT Shader is happy.
The swizzeling would be like this:
Original R → Lit G
Original G → Lit A
Original B → Lit R
I have so far not worked with Texture manipulation so far so i am a bit stuck.
My idea so far is to use GetPixels32 then loop over each Color-Entity and swizzle them and then use SetPixels to write them back and finally use Apply()
Is that efficient enough or are there some better ways?
Presumably you’re loading jpg or png texture files? If so, what you’re doing is mostly correct. Two things to be mindful of.
First is the GLTF ORM map uses roughness, while Unity uses smoothness, so it’s not just a straight swizzle. The roughness (G) needs to be inverted when written to the alpha. That’s simple enough: newColor.a = 255 - color.g
Second issue is any texture loaded from the web is always going to be flagged as being a color texture, ie: it’ll have sRGB enabled. The ORM texture is expected to be in linear space. How much of an issue this is for you depends on the content, but AO will look different, as will the metalness since those are both going to be stored in the RGB channels that are effected by gamma correction when sRGB is enabled. When swizzling the content in c# this isn’t an issue though. But you may want to copy the pixel values into a new Texture2D created with linear color values enabled.
Color32[] colors = tex.GetPixels32(0);
for (int i=0; i<colors.Length; i++)
{
Color32 newColor;
newColor.g = colors[i].r;
newColor.a = 255 - colors[i].g;
newColor.r = colors[i].b;
colors[i] = newColor;
}
// new texture with source texture's width, height, format, with mips, and using linear color space
Texture2D newTex = Texture(tex.width, tex.height, tex.format, true, true);
newTex.SetPixels32(colors, 0);
newTex.Apply();
// newTex.Compress(); // optional to compress to DXT5 for desktop platforms