TM Opacity Mask Packer
A small tool that packs up to 8 different binary opacity masks into one 8bit grayscale image to save a considerable amount of memory (up to 25%). Encoding can be done in Unreal Engine or Substance Designer/Substance Player - decoding happens with a material function in Unreal Engine.
Usually, opacity masks are loaded as 8bit images as the GPU can only process 8bit data blocks, while the effective information used in the shader is a binary mask determining whether a texel is rendered opaque or transparent. There is no in-between, and the 8bit image gets clipped to either white or black in the shader, resulting in a huge waste of information and memory.
USAGE & INFO:
This tool doesn't work well with mipmaps, as the mipmap filter algorithm distorts the data and introduces artifacts after encoding. However, you can get usable results, even in the most extreme cases, by using high sharpen or even unfiltered mipgen settings, and even then it will introduce a cost in detail. However, depending on your needs, these losses in quality can be justified by the amount of memory saved. The tests made here were done with 8 needle masks - the higher the detail in the masks, the higher the loss in compression. I tried to find the most extreme example to give an idea of what can be done.
How to use:
- Use the .sbsar in whatever form you like (either in Substance Player, Designer or the UE Substance Plugin) to generate the packed masks.
- Copy the .uasset file into your project's content folder and import the packed texture.
Make sure it is set to Grayscale with sRGB unchecked. In the mipgen settings, set it to something between sharpen0 and unfiltered, depending on what works best in your case.
- in UE, drag the MF_TM_MaskPacker Material Function into your foliage material and add a TextureCoordinate node, as well as a scalar parameter.
Drag your texture in the material, right-click, and convert to Texture Object. Plug in the nodes to the respective slots in the material function. The number selection needs whole numbers starting at 0 (so 0-7), where 0 is Mask 1 from the Packer. Use the output of the function as your opacity mask.
Tips:
You lose bilinear filtering, as well as the mipgen filtering if you use this method. This results in finer and noisier details, while at the same time in more artifacts because of that. Compared to not using this packing method, you can try to make the mask denser in the packing node. You can use the inbuilt histogram scan, or add padding. Sometimes (for these needles for instance) you need to add a bit of padding and experiment with which values work best in your case. Every mask input in the packer .sbsar has a histogram scan and padding slider. Mind that if you use padding, you need the other maps to have padding as well. By default, SpeedTree doesn't add padding. So you need to add it yourself with a distance node in SD or in Photoshop. You can also use the TM Solidify (free) to get an effect in SD like with the flaming pear solidify filters for Photoshop.
The package contains a mask encoder based on Substance Designer/Player, and a .uasset material function to be used inside any material in Unreal Engine.