I am extracting Normal Map from Texture2DArray in shader graph and then converting it to normal using Normal Unpack node. But results I get are different, compared to usual Texure2DNormal Map. Texture2DArray Normal doesn’t work correctly at all, except it just makes terrain look darker.
Texture2DArray is generated using TextureFormat.RGBA32 as well.
I’ve tried setting import settings of normal as “Normal Map” and as “Default”. Normals are a bit different in both cases(When generating with import setting of “Normal Map”, it becomes Red, when generating with setting of “Default”, its colors are more correct), but overall results are the same - dark terrain without correct lighting in both cases.
Thanks for any help!
Unity’s normal maps are packed into one of three possible layouts.
On mobile they’re generally just stored exactly like the imported texture, ie: no modifications are made apart from making sure the texture is marked as being linear (ie: not sRGB), which is required for all normal maps on all platforms.
On desktop & console they’re packed either as a specially setup DXT5 or BC7 texture (which the inspector shows as DXTnm or BC7 UNorm), or as BC5.
DXT5 and BC7 textures are stored with the original source texture’s red channel moved to the alpha channel, and the green channel copied to both the green and blue. The final texture’s red channel is set to 1.0.
For BC5 textures the red and green channels are left as they are, but the BC5 format has no blue or alpha channels. Shaders still get a float4 value when the texture is sampled, but the blue is always 0.0 and the alpha is always 1.0.
The Normal Unpack node set to tangent space assumes the normal map is packed in either of these two formats, but does not actually know which one is being used. Instead it always multiplies the alpha and red channel together for the x, then reconstructs the z from the rescaled x and y. This should work with normal maps that aren’t using any special packing too. But if you use a DXT5 or BC7 format for your texture array and are storing other data or 0.0 in the alpha channels, the Normal Unpack node will fail to produce a proper normal vector. It’ll also fail if the texture isn’t set to be a linear space (non-sRGB) texture.
You can try setting the Normal Unpack node to Space > Object, which skips the special channel unpacking and z reconstruction and instead just does the basic normal.xyz = tex.rgb * 2.0 - 1.0;. But if that still doesn’t work it probably means you have sRGB enabled on your texture array.
How do I set TextureArray to be in a nonSRGB texture? I can set individual textures to disable sRGB, but after TextureArray gets generated is seems to be sRGB again.
The setting on the individual textures is somewhat irrelevant, as you’re copying the texel data from the the original texture into the array, and the texel data doesn’t say anything about if it’s sRGB or not.
When you create the Texture2DArray you need to set it to be linear.
That worked, but non-sRGB looks very ugly and light on albedo texture, so if I wanted to use sRGB texture array together with Normal maps, I’d have to convert sRGB to non-sRGB in my shader graph( just for normal map) right?
Albedo and normal textures are fundamentally incompatible. You really want to use two separate texture arrays and not combine them into one. If you convert either the albedo to linear, or the normal to sRGB, means you’ll see significant banding in the data. If you’re really intent on doing it that way, keep the texture array linear and convert the albedo in the shader. You can use Unity’s built in GammaToLinearSpace(col.rgb) function, or you can approximate it cheaply with pow(col.rgb, 2.0).
Case you don´t solve your problem, I made this to extract the normal map from a array. Connect the texture2DArray to SampleTexture2DArray(one for each of texture in array using index) and then for each one, multiply by 2, and subtract 0,5. Now link to NormalReconstructZ node and link this to NormalStrenght node. create a float property to use as strenght and add all normals and connect to normal at master stack.