Storing Specular, Roughness, etc. in a Single Image?

(I’m really a programmer but I’m starting to dabble in the art side, so be forgiving!) I’ve sometimes seen the “texture maps” of various material channels stored in one file on different channels; E.G. Specularity, which AFAIK can be represented on a gray scale image (I.E. values of 1-255), is stored in the Red channel, another is stored in Blue, another in Green, etc.

Is this easier on performance? Is it more convenient than multiple files? What are some reasons for this?

Also, are there any resources on techniques for this?

The Dota2 art guides are really good at showing off how they use this technique.

AFAIK it saves overall file size as you are using 1 file instead of 2 or 3. It also lowers the number of textures that have to be loaded and referenced.

Draw calls, and memory allocation. Ultimately, a roughness map is only a scalar value, but you’re wasting the space of 3 independent scalar values by just importing the map on its own. You can save 2/3 of the memory by using one texture to store roughness, height, and ambient occlusion values in a single texture. Alternatively, you can forego compression. You’ll use a bit more memory, but the quality will be better than if you used a texture 4 times bigger (by area). But just throwing in a roughness map with standard compression for colors is a terrible, terrible idea. Using the linear space (no sRGB) and all 3 channels of a colored texture is the most efficient.

Second is draw calls; materials can only have 16 texture sample slots and some of those are dedicated to reflections and lighting, so you’re limited to anywhere between 12-9 textures per material. On top of that technical limitation, every single one of those textures requires an individual draw call to pull it in. If you use one texture, you can limit the draw calls to just the texture, and if you use a shared sampler, you can share all the textures you might need and batch load them all in one go. But if you choose to use shared samplers, you can easily blow out your memory budget if you’re not careful managing your texture space. Calling in tons and tons of 2K textures when you don’t have to really won’t help.

Roughness, displacement, ambient occlusion, opacity, subsurface opacity, grayscale detail textures, and material masks can all be stored in single-channel values in linear space to save a hell of a lot of memory (you might need to raise grayscale detail textures to the power of 2.2 to look appropriate, or multiply it by itself for a fast approximation for good colors, but everything else works as it should in linear space, which uses less memory than gamma space).

The material below was made with only 4 textures: a colored texture map, a normal map, a detail map to provide each brick with a different value, and a combination texture of a mask, roughness, ambient occlusion, and displacement map. None of the textures are larger than 512x512, and all of the assets combined make up less than 1 MB in textures.


You can easily store Roughness, Metallic and Specular(SpecLevel) in one texture utilizing the channels, R, G, B to be specific. Ignore the Alpha channel for now, because sometimes it doesn’t save properly as a seperate channel in Substance. (For example, saving as a PNG with an alpha channel input will basically just make the PNG transparent in RGB level. Alpha channel is not existent after you save it).

In fact, specularLevel doesn’t serve a lot of purpose in UE4. You can simplly ignore it most of the time. Though if you wish to have something with no shading at all, you can turn metallic and specular both to 0, and it will look as flat as possible.

I recommend doing so with Roughness in the R channel, because the intial. Metallic in the G channel, because it’s next important thing. And specularLevel, or whatever mask you need, into the B channel. Because anything else is either least important or extra stuff.

Though one thing I found is likely useful is the height information map. You can put that into the B channel, not because it will give you any visual fidelity on its own, but you can then use it to blend anything that uses height information, like water puddle, snow, dirt, whatever.

For best quality/memory you should store single channel maps as Alpha textures. This is non sRGB format that use high quality BC4 compression. 8-bit endpoints with 4-bit indices. Color compression formats(BC1, BC2, BC3) are bad for separate channels because they don’t handle channels separately.

Thanks for all the replies, especially Mariomguy. Also, Steve_T, that DOTA guide is massive! Any other places you recommend where I could find such resources?

A quick note regarding use of the alpha channel. Using one channel for each grayscale texture is a practice I’ve used since UDK. However I use the Gimp and can’t seem to write directly to the alpha channel for this purpose. Anyone have any success using Gimp to store a texture in the alpha channel of a TGA?