Skip to main content
GameDev.net gamedev.net
🔒 Locked

rgb normal map question

Started by magneeto Dec 29, 2006 at 8:27 AM 2 replies 1.1k views
Original Post
magneeto
magneeto
hi, i would like to know the basics behind the formula for converting a normal map to rgb image. for example i've seen this conversion in a code ... R = (normal.x+1)*128 G = (normal.y+1)*128 B = (normal.z+1)*128 and i'd like to know the derivation.
Nik02
Nik02
A RGB pixel with 8 bits per each channel typically1 stores it's components as unsigned bytes ranging from 0 to 255.

Since a normal is a three-component vector which components' ranges are from -1 to 1, you need to map -1 to 0 and +1 to 255 by using the conversion formula f(x) = (x + 1) * 128.

Note that if x is 1, the result will overflow an unsigned byte by one, so be sure to take this into account and clamp or scale the value as needed by your shaders.

1 typically, but not strictly necessarily
Niko Suni
Todo
Todo
Quite easy. In a RGB colour texture map, each texel represents a colour using three channels. Each channel ranges from 0.0 to 1.0 inclusive (so [0;1]). In a normal map, these channels however represent encoded normals. Decoding would mean - in this context - mapping the interval [0;1] back to [-1;1]. Here's the derivation for one channel x (equivalent answers exist for y and z):

x = x * 2.0;   [0;1] => [0;2]x = x - 1.0;   [0;2] => [-1;1]


The reverse operation (encoding, which what you want) then boiles down to:

x = x + 1.0;   [-1;1] => [0;2] (0)x = x / 2.0;   [0;2] => [0;1]  (1)


However, in the example you mention, the resulting texture uses (I guess) 8-bit channels instead of floating point channels. These range from 0 to 255 inclusive. This involves a simple scale to map the interval [0;1] to [0;255]:

x = (byte)( x * 255.0 );  (2)


combining (1) and (2) gives us:

x = (byte)( x / 2.0 * 255.0 );=> x = (byte)( x * 255.0 / 2.0 );=> x = (byte)( x * ( 255.0 / 2.0 ) );=> x = (byte)( x * 127.5 );  (3)


and as such:

x = x + 1.0;              (0)x = (byte)( x * 127.5 );  (3)=> x = (byte)( ( x + 1.0 ) * 127.5 );


for all three channels.

PS. The normal maps are taken to be normalized beforehand, otherwise after decoding you'd need to normalize them manually.

EDIT: beaten to it ;-)
magneeto
magneeto
thanks a lot.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.