UnpackNormal(fixed4 packednormal) role ?

Hello !

I really don’t understand the UnpackNormal( ) function…
Let-alone the code inside “UnityCG.cginc” …

inline fixed3 UnpackNormal(fixed4 packednormal)
{
#if defined(SHADER_API_GLES)  defined(SHADER_API_MOBILE)
	return packednormal.xyz * 2 - 1;
#else
	fixed3 normal;
	normal.xy = packednormal.wy * 2 - 1;
	normal.z = sqrt(1 - normal.x*normal.x - normal.y * normal.y);
	return normal;
#endif
}

Thanks in advance !

1 Like

Unity stores its normal maps as DXT5nm, where only the G and A channels are used (because they have more bits available).

normal.xy = packednormal.wy * 2 - 1;

Takes the x from the A channel and the y from the G channel, then converts them from the 0 to 1 space to the -1 to +1 space.

normal.z = sqrt(1 - normal.x*normal.x - normal.y * normal.y);

Reconstructs the z value from the x and y values since the z isn’t stored in the normal texture.

1 Like

Thanks for the answer but it’s hard to understand … Do you have some links/papers in order to improve my skills on this subject ?

I wrote about it here;

http://forum.unity3d.com/threads/82652-Normal-maps-(and-importing-them-correctly)?p=629189&viewfull=1#post629189

Ultimately, you don’t have to understand what it does other than you pass in a compressed normal map (texture tagged as normal map in the inspector) and you get out a proper normal map.

It should be noted that “packednormal.wy” is exactly the same as “packednormal.ag”, it’s just another way of writing it.

I wrote an explanation here: GLSL Programming/Unity/Lighting of Bumpy Surfaces - Wikibooks, open books for an open world
(And I have a professional interest in it being understandable; thus, I would appreciate comments.)

Also note that the motivation for using only two components in OpenGL is somewhat different from what Farfarer has described: in OpenGL Unity might use a two-component texture which actually offers only two components A and a color component, which can be accessed as R, G, or B.

Huh, I didn’t realise OpenGL did different stuff. Interesting. What texture compression does it use?

The swizzled DXT5nm stuff is for improved compression quality.

I wasn’t aware of it, but apparently OpenGL 4 supports its own compression format (see appendix C in the specification: http://www.opengl.org/registry/doc/glspec42.core.20110808.pdf ). In OpenGL ES the supported compression formats depend on the GPU.

However, in OpenGL you can always ask for a two-component texture format with (for example) 8 bits per component. Thus, the driver could use, for example, 2*8=16 bits per texel. In that case, you have to store one of the components in the alpha channel and therefore you have to do some swizzling, too. Thus, I wasn’t surprised to see it.

Oh, very cool. So it’s smaller than DXT5 (16bits as opposed to 24) and with better fidelity. Wish DDS could do the same thing :stuck_out_tongue:

Doesn’t DXT5 use 8 bits per pixel? (That’s what wikipedia says: http://en.wikipedia.org/wiki/S3_Texture_Compression#DXT4_and_DXT5 : 128 bits per 16 pixels = 8 bits per pixel)

It is, but it’s lossy compression. The 16 bit per pixel format he was talking about is uncompressed, so you save 33% of the size with no quality loss.

DXT gets 5:6:5 for R:G:B
DXT5 is 5:6:5:8 for R:G:B:A

So with DXT5, only the alpha channel remains uncompressed (hence the swizzling with the normal map - uses the G and A channels because they’re least compressed).

Errrrrr … OK. Do you have any references that support this claim?

That wiki article you posted.
http://tech-artists.org/wiki/DDS
http://tech-artists.org/wiki/Normal_map_compression
http://ianguthridge.com/?tag=dxt

Apart from http://tech-artists.org/wiki/Normal_map_compression, all these references make it clear that 16(!) 8-bits alpha values are interpolated from just 2(!) 8-bits alpha values (with only 8 different linear combinations). This is not exactly uncompressed. :slight_smile:

Oh, it’s definitely compressed, it just doesn’t use bit reduction and stays at 8 bits, unlike the RGB channels which are reduced to 5/6/5 respectively.

Ah, yeah, uncompressed was the wrong phrase to use. Substantially less compressed would be a better description :stuck_out_tongue: