Sign in to follow this  
Elvis Enmanuel

Pack normal and height data in one float texture

Recommended Posts

Is not a question. I just coded this and I think that can be useful. This two routines allows to store normal mapping data and terrain height in one float texture. In order to perform vertex texture fetch in the vertex shader we need to access to the topology with one float texture. I coded this in C++ but it's easy portable to GLSL or HLSL. In this example I store only 2 normal components: X and Y in range 0 to 255. Remember that you must extract third component as follows: sqrt( 1.0 - nx*nx + ny*ny ); Heightmap has custom precision values, due big imprecision of floating point conversion. With 11 bits of precision we can store heights from 0 to 2043. This happened because we loose 4 numbers with this precision. The formula is: unsigned char hPrecisionBits = 11; // (1<<11) = 2048 unsigned char expectedError = 1 << (hPrecisionBits - 9); // 4 unsigned short maxHeight = (1 << hPrecisionBits) - expectedError; // 2044 <code> //! Gives fractional number inline float frac( float _value ) { return _value - floorf( _value ); } // NX | NY | HEIGHT -> float32 // 8 | 8 | 16 inline float packNormalAndHeight( unsigned char _nx, unsigned char _ny, unsigned short _height, char _hPrecisionBits ) { return (_nx / 256.0) + ((_ny / 256.0) / 256.0) + (_height / ((float)(1<<_hPrecisionBits)) / 65536.0); } // float32 -> NX | NY | HEIGHT // 8 | 8 | 16 inline void unpackNormalAndHeight( float _value, char _hPrecisionBits, float* nx_, float* ny_, float* height_ ) { *nx_ = floorf( frac( _value ) * 256.0 ); *ny_ = floorf( frac( _value * 256.0 ) * 256.0 ); *height_ = frac( _value * 65536.0 ) * ((float)(1<<_hPrecisionBits)); } </code> Usage example: unsigned char hPrecisionBits = 11; // (1<<11) = 2048 unsigned char expectedError = 1 << (hPrecisionBits - 9); // 4 unsigned short maxHeight = (1 << hPrecisionBits) - expectedError; // 2044 // Pack as 8 | 8 | 16 float packedValue = packNormalAndHeight( 249, 37, 1432, hPrecisionBits ); // Unpack from single float float x,y,h; unpackNormalAndHeight( packedValue, hPrecisionBits, &x, &y, &h ); Notice that 'expectedError' brings us the amount of error values returned in height function. For example, if our precision bits are 9, expected error will be 1 (135 when we store 136 number). For 10, error will be 2, for 11, will be 4, for 12 will be 8, etc... http://gamedusa.blogspot.com/2010/03/pack-normal-and-height-data-in-one.html

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this