Home Unreal Engine

Deconstructing foliage shader from Rural Australia pack, question about packed texture

veteran polycounter
Offline / Send Message
Alex_J veteran polycounter
Hi, I am studying the Rural Australia package and can't figure out how a texture channel has been packed and is being used. 

The Blue channel in the Normals texture sample:


The comment suggest that two value ranges are being read somehow? 

(below image) This is where the Blue channel leads. It looks like a little math is done to derive something useful. I can just punch in some values and make use of the shader, but if anybody can explain in simple terms what is being done here that would be awesome. 

I did contact the author but he hasn't responded so far, if he does I'll pass on any info here. 


Replies

  • Alex_J
    Offline / Send Message
    Alex_J veteran polycounter
    Actually, just got answered: 


    from the author:

    Hi!

    There's a need to pack textures as tightly as possible in order to have as few texture fetches in shaders and less (texture) memory. There is a trad-eoff with quality however, some textures need high quality, and others don't. Normal maps typically need high quality as pixellation can otherwise be quite noticeable in the final result. Depending on your texture format, it also matters which channel you pack your textures in to. Regular DTX compression generally deteriorates the blue channel more than others, however other formats such as BC7 usually distribute the quality across channels evenly, at a higher cost. SSS and Roughness are 2 textures that don't really need high quality for a good end result, which is why I have packed both of those in to a single channel, and instead of using the full 0-255 range of the channel for one, i have split the range into 2, 1 for each texture. 0-128, and 129-255. This obviously reduces quality of each, but is barely noticeable in the end result.



    I'm still not sure how I can put two textures into a single channel like that though. I guess it operates on assumption that the two values will always be somewhere in the specified range.

  • poopipe
    Offline / Send Message
    poopipe high dynamic range
    its not entirely straightforward - conventionally you'd use bitwise operators for this sort of stuff. 

    here's a link to get you started 
    https://gamedev.stackexchange.com/questions/7859/hlsl-pack-4-values-into-32-bit-float

    I'm fairly confident it can be done in substance designer - it doesn't have bitwise operations but should be possible to use multiplies and adds 

    unreal may have bitwise operators in shaders  - if so you should be able to render the packed version out of a shader
  • Alex_J
    Offline / Send Message
    Alex_J veteran polycounter
    @poopipe

    I think I need to understand some more 101 stuff first... for instance, there is a difference between targa file and png file. There is 8 bit depth, and 16 bit depth. But I don't know what the differences are, or why they matter, beyond a few basics. Like to have an alpha, that requires more bits (more data, I guess). 

    Is there any good resource that breaks this down at beginner level? I'm not sure what the subject would be called. I guess if I did some shader writing 101 that would probably cover it?

    The practical application is that when I am looking through a material like this, I can understand why they use X compression method, and packed textures a certain way, used a certain image file, etc. 

    And of course, be able to optimize my materials better as well.
  • poopipe
    Offline / Send Message
    poopipe high dynamic range
    What's been done in this shader is unconventional and tbh looks a bit masturbatory 
    Personally I'd have taken the sss and roughness out, compressed them as a 2 channel texture and halved the size if I was desperate to save memory.  if the cost of one extra texture read per tree material is causing you problems then I'd suggest something more fundamental is wrong


    anyway.. 

    I dont think you'll learn much about this if you google basic shader creation - this is verging on render/engine stuff . 

    I'll try to explain the very basics here.. 


    All image formats are fundamentally the same thing. i.e a file contains a 2D array of floats, integers or (in the case of multi-channel images ) 1D arrays of floats or integers. 
    The actual file format is pretty much irrelevant outside of it's featureset - these can get pretty weird (tif is insanely flexible/complicated, exr can have shit loads of channels - all at different dimensions and bit-depths, jpegs are evil and tga is pointless now we have png)  wikipedia is a pretty good place to look up the specifics 

    bit depth == precision
    an 8 bit image has to 255 steps between 0 and 1, 16 bit has 65536  and 32bit has fucking loads -  this is per channel.  the more bits you have, the more gradations between black and white can be represented

    This is all basically irrelevant  once you import the image though. At that you're working with GPU friendly compressed data.  there's a lot of compression formats and they all have pros and cons but they almost all result in less precision. I forget the name but the traditional basic rgb compression gives you 5, 6, 5 bits (r, g, b respectively)  or 32, 64, 32 values - you'll note that this is a shit load less than the 65536 you started with. 
    it might be a bit tricky to link an unreal compression option with an actual named compression method since it's a cross platform engine but you'll be able to look up things like BC1, BC5, BC7 on wikipedia and get an idea of what the methods do. 
    I wouldn't get too worried about it unless you want to start poking engine code or get a couple of maths degrees and invent a new compression method, its enough to know what's the most appropriate option  for your given use case and you work that out by trying them. 



  • Alex_J
    Offline / Send Message
    Alex_J veteran polycounter
    @poopipe, thanks! 

    As a rule of thumb, if exporting a packed texture from photoshop, an 8 bit png will serve most purposes? Any reason to use higher bit depth?
  • Alex_J
    Offline / Send Message
    Alex_J veteran polycounter
    Understanding Texture Maps - Shader Graph Basics - Episode 5 - YouTube

    Ben Cloward just uploaded a video covering just this topic on youtube, I'll leave link here as it adds on to info here and may also help someone searching in future.
  • poopipe
    Offline / Send Message
    poopipe high dynamic range
    Alex_J said:
    @poopipe, thanks! 

    As a rule of thumb, if exporting a packed texture from photoshop, an 8 bit png will serve most purposes? Any reason to use higher bit depth?

    It's been my experience that feeding 16bit textures into the compression process gets you better results - particularly with normal maps. This is not something I've tested properly in Unreal but as a rule the better quality your input- the better quality your output.

    in practice you're very, very unlikely to see a notable difference with foliage - its much more likely to be a consideration on large flat surfaces

    Probably worth noting that Unreal specifically does not handle 16bit color images in a friendly way. It treats them as if values are stored in linear space and automatically applies an sRGB transform  - this is what causes the washed out basecolor/emissive that surprises everyone 
    If you're using substance designer to output textures this is fine because you can set your export up to accommodate - in photoshop it's a bit of a dick
  • Alex_J
    Offline / Send Message
    Alex_J veteran polycounter
    good to know, thanks! @poopipe

Sign In or Register to comment.