I also posted the same question in the technical talk sub-forum:
http://polycount.com/discussion/184005/normal-map-compression-and-channel-packing
To avoid having split threads (and repair my mistake), consider posting your reply there instead!
Intro:
I've already spent 2 days trying to understand this and lost sleep over it. I have read through the relevant (and more) polycount wiki articles, unreal engine documentation, plenty of forum threads both here and on the unreal forum and I've also read up on texture compression in general. But I feel like there's something I'm missing that I just can't figure out by myself. So I'm turning to you guys for help.Goal:
I'm trying to pack my textures in a smart way, so that I'll only need to load 2 textures for each of my materials:
-Base Color in RGB and height in A.
-Normal map in RG, AO in B and roughness in A.
Background:
I'm sure many of you have seen this done correctly before. I've seen this done correctly
before (here is an example of someone who has done it correctly before:
http://polycount.com/discussion/comment/2521188/#Comment_2521188). I just don't know what I'm doing wrong.
I packed the channels in Substance Designer (I've tried exporting with both default format and DXT5, if that's even relevant) and double checked and controlled that the channel packing is correct in Photoshop with both png and tga files. - With that said, I don't think there's anything wrong with the packing.
In Unreal, I use this shader and these compression settings:
The normal/AO/roughness texture is set as "Sample Type: Linear Color" (as I get error messages otherwise).
As far as I know, this should be right and should do the trick. Side-note: I don't find there to be any difference between the BC7 (which I've been told to use) and the default setting (DXT1/5,BC1/3). The HDRCompression setting (BC6) renders a better result but also shoots the resource size through the roof.
The problem is that it looks shit:
I was prepared for a visual down-grade and less accuracy within the normal map (since the blue channel needs to be calculated through the RG channels). But the results I'm getting are far below what I was expecting.
However, I quickly noticed that this was only the case after I saved/compressed the texture within Unreal (the uncompressed file, right after import, renders great results, almost indistinguishable from how it looks without packed textures):
The first image shows what the texture should look like (screen shot taken with non-packed textures) and the second shows what the texture looks like (screen shot taken with packed textures with the given shader above).
Here are samples of the packed normal map, uncompressed (the first one) and compressed (the second one, using BC7 compression):
I further tracked this to the R and G channel being the issue. Here are some samples of each of the four channels. The first one is "how it should look" (what it looks like in the non-packed textures) and to the second one is what it looks like (in the packed textures).
Please note: The image showing the packed channel (the second one) is at the point in the shader after I multiply the channel by 2 and add -1.R:
G:
B:
A:
As we can see, the issue appears in the R and the G channel (only in the normal/AO/roughness map, not in the base color + height map, which uses the same compression with the exception that it's checked as sRGB and is set to "Sample Type: Color" instead of "Sample Type: Linear Color" in the shader). I don't know what is happening here, if the channels are for some reason rendered at a lower size than they should, if they are sampled in the wrong way, if they are poorly compressed or if the moon is 37 degrees too far to the south in relation to mars (I don't find this last reason to be too likely, though).
Or is it supposed to be like this and I'm just overestimating the value of packing textures this tight? Is is supposed to look this shit?
Please, halp! I'm really tired of this and I just want it to work.
Replies
Hey Daniel!
I just See your post. everything you did work,
The only problem is the DeriveNormalZ node dont work really well.
BC7 is great to keep the same Quality with Color Linear to be sure to not have problem with gamma
Use this math to recreate your Blue Channel and after. add at the end Normalise
Muliply by 2.5 add -1 and you should have the same result of the one not modify
I was having the same issue and I found the correct solution from this video. Basically, append R&G together then multiply x2, subtract 1, then derive-z. Although the compression of BC7 is not as good as the Normal map compression, this still yields very nice results.
https://www.youtube.com/watch?v=m5bP-xc6Sgs