lunes, 29 de marzo de 2010

Pack normal and height data in one float texture

Wow, hard coding night. But in the end I can code two routines that allows me to store normal mapping data and terrain height in one float texture. Remember that 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

//! 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));
}


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( 231, 137, 2043, 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...

I hope it will be useful.

5 comentarios:

The Dr. dijo...

No me he enterado de una papa Elvis :D

Anónimo dijo...

I am sure you will love RxFNLngC [URL=http://www.adjustable--dumbbells.com/]bowflex 552[/URL] to take huge discount jhLqNweg [URL=http://www.adjustable--dumbbells.com/ ] http://www.adjustable--dumbbells.com/ [/URL]

Anónimo dijo...

view tjkBdfUO [URL=http://www.adjustable--dumbbells.com/]bowflex selecttech 552 dumbbells[/URL] to your friends MUrnECdm [URL=http://www.adjustable--dumbbells.com/ ] http://www.adjustable--dumbbells.com/ [/URL]

Anónimo dijo...

you love this? wkUTzbUo [URL=http://www.cheapguccireplica.tumblr.com/]gucci outlet online[/URL] to your friends PQJkGJCX [URL=http://www.cheapguccireplica.tumblr.com/ ] http://www.cheapguccireplica.tumblr.com/ [/URL]

Anónimo dijo...


It is corner kick! Bai Ren 2013 head break a ball to repeat on nightmare of sports season final
Corner kick became Nuoyier again defend soft costal region, this can'ts help letting Bai Renqiu confused memory to remove most that agonized night year ago. In the Europe coronal final that bringing couplet court, the Bai Ren that killed Qieerxi absolutely almost by Deluoba the head of last hour attacks door place to break even, the play away in nodding ball big fight finally the match. That corner kick, it is Qieerxi full-court match the chance of only a corner kick inside 120 minutes, but the deadly sock that made knockdown Bai Ren however. In corner kick the Bai Renmu Buddhist nun of the error in defending is black, can nurse a grievance finally only " results " the 3rd runner-up of this sports season, became " 3 inferior king " . See this corner kick throws a ball, fan people also can rejoice only this break a ball to did not bring serious consequence. Mere after this corner kick throws a ball 20 minutes, manzujiji helps Bai Ren reentry the impetus that one ball squelched Asenna kickbacks thoroughly. This loses a ball, it is Bai Ren loses a ball in the first of 2013, in [url=http://www.palmexpo.in/jordansforsale.aspx]cheap jordans for sale[/url] 5 of 2013 formal matches before this, bai Ren is hit into 13 balls and all 0 adversary, performance is extremely excellent, can says " the first line of defence of European " . But this corner kick loses a ball terminative the outstanding play of Bai Ren line of defence, also ring alarm bell noisy to team. In the Europe coronal competition that eliminates in such two bouts, any opportunities are become likely kill machine, once had eaten the deficient Bai Ren that placement defends, must solve this problem well in training.
Article origin: Netease sports writer: Ma Li abstruse