Search Unity

Standard Shader (Metallic) Texture Packing

Discussion in 'Shaders' started by echo4papa, Mar 27, 2015.

  1. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    I noticed something in the Standard shader that surprised me. The Metallic Map uses the R channel for metalness, A for gloss/smoothness, and G and B channels are ignored.

    But both Height and Occlusion both use the G channel only, and ignore RBA.

    Would it make sense to change one of those to B so that a map can be packed as such:

    R: Metalness
    G: Occlusion
    B: Height
    A: Smoothness

    It seems that having both Occlusion and Height on G is a bit of a waste because it requires them to be individual textures.

    If there something I am missing as to why both are on G, or was one supposed to B from the get go?
     
    mowax74 and the_motionblur like this.
  2. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,735
    It's for ease of use. Also, the shader automatically turns on/off features depending on which maps are plugged in, so having everything be packed in one map would break that feature (although arguably, there could be checkboxes added).
     
  3. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Ah, interesting point.

    They could still be separate sampler2Ds, just all sharing the same source texture. As it stands now you could put either height or occlusion in the G channel of your metallis map and just assign that texture to both places.

    Would be an interesting performance tweak though to have them share the same sampler2D if they are the same source texture.
     
  4. the_motionblur

    the_motionblur

    Joined:
    Mar 4, 2008
    Posts:
    1,774
    If you don't plug something into the height channel it gets ignored. But if you want to use height and Ambient Occlusion you still need an extra texture, if the definition is correct.

    I don't see how this would break the feature, though. The height map is a greyscale channel no matter if it's located in the G or B channel. So how is this either for ease of use or feature breaking?
     
    mowax74 likes this.
  5. the_motionblur

    the_motionblur

    Joined:
    Mar 4, 2008
    Posts:
    1,774
    *bump* I'm actually still a little confused about this ...
    Could maybe someone from Unity please respond why the green channel is used twice instead of using the blue channel or a separate greyscale file for height? It's also definitely not just labeled wrong. The green channel actually uses either height or AO.
     
    mowax74 likes this.
  6. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,735
    The theory is that you use completely separate textures. They are expecting people to have separate maps and plug them where they need them, they don't expect that users are going to be concerned with which channel does what.

    The reason they keep sampling the Green channel, is that it usually compresses better. For example, DXT1 "uses a 565 compression for this, which means that red and blue are stored with 5 bit and green with 6 bit".
     
    the_motionblur likes this.
  7. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    The compression makes sense, however, why then does metallic also not use G?

    Either way, it's just an interesting choice.
     
    mowax74 likes this.
  8. the_motionblur

    the_motionblur

    Joined:
    Mar 4, 2008
    Posts:
    1,774
    Yes ... I didn't know the thing about compression, either. But I wonder - does "compressing better" mean that it's got higher compression and thus more artifacts or lower compression?
    I would asume it has a higher compression. So it's debateable whether AO or height can easier lose quality.
    But then again ... if it's the case of compression/artifact ration - why not use a simple greyscale instead of a whole different texture with only the green channel in it?
     
  9. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah its a lot slower for busy scenes bandwidth wise. PBS should typically be just 3 textures: albedo, normal and a packed data texture, with albedo alpha being reused for anything else you want.

    I did encourage Unity in alpha/beta to consider packing more data, or have all the textures separate, with Unity editor auto-packing but it fell on deaf ears, I guess its up to the individual developer to implement.
     
    mowax74 and the_motionblur like this.
  10. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,735
    That's a good question. I have no idea.

    No. Green channel for DXT uses 6bits while the other channels use 5. It simply looks better (less artifacts) than the other channels.

    I'm not trying to defend what Unity has done, but it seems to me that it has *some* rationale behind it.

    Although I have to say, having the editor do some auto-packing like hippo suggested would be awesome.
     
  11. SeveredScion

    SeveredScion

    Joined:
    Oct 16, 2012
    Posts:
    45
    OK I know I'm reviving an old thread but I can't find the official word from Unity on this anywhere. At the time of this writing (Mar 2, 2016) the official documentation for the height and AO channels at http://docs.unity3d.com/Manual/StandardShaderMaterialParameterHeightMap.html and http://docs.unity3d.com/Manual/StandardShaderMaterialParameterOcclusionMap.html does not actually list which texture channel these maps should go in. The only place I see this documented is in the pop-up in Unity when you mouse over each channel name - it says "Height Map (G)" and "Occlusion (G)."

    This is extra frustrating when using the Specular workflow as opposed to Metalness, since there are no textures that have a spare green channel. Albedo, Spec, and Normal are all full-color RGB, which means if we want to use Height (aka Parallax) maps and Occlusion, we have to add 2 additional RGB textures, just to get the Green channel from each.

    As far as I understand, other methods of compression are replacing DXT, so if that's the only reason for putting all the maps in the green channel, can Unity just let that go? It seems to me it would make more sense to put the Height map in the alpha channel of the Normal map, since Height is not used without a normal map, anyway. And this would match the DX11 shader defaults. And if Occlusion defaulted to the Alpha channel as well, then for any textures that did not use transparency, Occlusion could be packed in the Alpha channel of the Albedo texture. From a user perspective, this would be easier and more intuitive than forcing us to create 2 new otherwise non-existent texture files just for the green channels.

    I'm an artist not an engineer so my technical understanding of this is not great, but I suppose that only the used channels are loaded at run-time, so even if it takes more hard drive space to load in additional textures, it doesn't take up more RAM/VRAM for the player?

    Honestly I'd love being able to pick which texture channel to use, which I'm sure is code-able, but I surmise that locking each map type to specific channels makes it much easier for Unity to optimize the Standard shader's ability to ignore unused map channels.
     
  12. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I doubt there's any performance gain to be had from using only one channel, you still pay the cost for 1 or 4 as I understand it... although at a guess I imagine compressed formats would be a bit cheaper. See what any experts stumbling by have to say?

    If the worry was about packed textures, then I think those are widely understood by users now, they realise stuff needs to be optimised.
     
  13. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    It's all just done for simplicity rather than optimization. The texture layout effectively doesn't change between the different options, it's just a matter of plugging in the right textures, and you can easily add or remove ones you don't need.

    Most people are just going to black to white greyscale for height and occlusion as these are what 3d packages and material generation tools tend to output by default. Makes sense to keep them that way.

    Normals are converted to what's referred to as DXT5_nm which uses the green and alpha channel of a DXT5 texture to store normals. This reduces the block artifacts from using DXT1 normals straight. You could use the other two channels, but normals are especially sensitive to compression artifacts so it's not usually a good idea to use them for anything else.

    I believe some of the community PBR shader packs did for a while, but I think they all went to using the diffuse alpha for alpha again. It makes sense for packing, but some confusion for users especially when a lot of them are probably going to just put in a diffuse texture and nothing else.

    So it's totally possible to pack these textures tighter, and swizzle based on input, but there's lots of complications there when it comes to texture reuse. So it's easier to just keep things uniform even if the packing isn't as nice. It also potentially makes for more shader variants.

    If you want to use a different packing it's totally possible to setup stuff however you want with your own custom surface shaders. Since in surface shaders you have to write the texture sampling and assignment people are free to swizzle S*** all they want.
     
  14. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Also, if you dig into the shader code it's very clearly sampled from "G" for those textures.

    I've taken to using my own packing methods with custom shaders. I actually got adventurous and attempted to pack Albedo RGB, Metal, AO, Smoothness, and Normal into two textures(AlbedoRGB, Smoothness A, NormalXY-RG, MetalB AO A) for iOS. Little did I know PowerVR compression would destroy that idea...
     
  15. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I wouldn't have packed the normal. That's never worked out for me in the past. But packing the rest is a great idea.
     
  16. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    It worked very well for Windows & WebGL, but PVRTC with an alpha channel adds too much noise to be used for normals.
     
  17. ceebeee

    ceebeee

    Joined:
    Mar 7, 2017
    Posts:
    395
    the documentation states: "Often (but not always) the greyscale image used for a heightmap is also a good image to use for the occlusion map." so that's probably why they both use the same channel, so they can be shared.