Jump to content

Best Fit Normals


LordHippo
 Share

Recommended Posts

Hello everyone,

 

I've implemented a really handy method for storing normal values in the gBuffer developed by Crytek.

The main idea is simple. The default way of storing normalized normals in the gBuffer, only uses some parts of RGB values.

As you know there are 256*256*256 values for a RGB value (with 8 bit buffers). So mathematically there are 16,777,216 values.

But when using normalized values, only 289,880 values are used.

So only %1.7 of values are used :):o:)

As you can see in the top image there are some artifacts in the reflected image.

 

This is not beacause 8-bit colors are not sufficient for storing normals, it's because we're wasting it completely :o

 

The simple way is to use 16 bits for normal buffer. But it would use twice the memory, and is slower.

 

This method tries to fit the normals in 8 bits with the quality of 16-bit normal buffer :D . It tries to find the best length for a given normal direction, that when scaled and stored in 8 bits, are the closest possible to direction of original normal.

The length scales are pre-calculated and saved in a cubemap. So when storing normals in the gBuffer, all you have to do is to lookup the normal direction in the cubemap, and scale the normal by the value read from the cubemap.

 

gallery_84_110_481913.png

 

So as you can see the second is much better and almost has no artifacts.

 

Then the cubemap lookup is turned into a 2D texture lookup that has only one channel (TEXTURE_ALPHA8) which is really fast.

In my framework I load and bound the lookup texture in the beginning of gBuffer generation, so the bandwidth is saved.

 

So by using this method GPU memory, bandwidth, and time could be saved with NO drawbacks B)

 

Note: The texture attached is provided by Crytek.

post-84-0-76523300-1326141775_thumb.png

NormalsFittingTexture_2.rar

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

I don't understand how this compression works. The scale of the normal should always be 1.0.

 

Does it store a coordinate point, with 8 bits for each axis, that when pointed at results in the closest normal?

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I don't understand how this compression works. The scale of the normal should always be 1.0.

 

No, it's not necessary.

It can be normalized in every shader that reads normal from gBuffer.

I think most of the LE's shaders does this currently.

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

Then it's not a normal, it's a vector. But yeah, I see what you're saying.

 

It's surprising to me that a short vector would have more accuracy in some situations. I can't really picture a situation where a shorter vector would be more accurate than a longer one, since you will always have a greater resolution of pixels further away from the origin.

 

That is pretty nice.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Then it's not a normal, it's a vector. But yeah, I see what you're saying.

 

It's surprising to me that a short vector would have more accuracy in some situations. I can't really picture a situation where a shorter vector would be more accurate than a longer one, since you will always have a greater resolution of pixels further away from the origin.

 

That is pretty nice.

 

Yeah, mathematically it's not a normal.

 

But here in the picture you can see errors for different lengths as blue lines.

So as you can see longer is not more accurate actually.

The red arrow shows the best length, and the minimal error.

post-84-0-46838800-1326152306_thumb.png

Ali Salehi | Programmer

 

Intel Core i3 2100 @ 3.0GHz | GeForce GTS 450 | 4GB DDR3 RAM | Windows 7 Ultimate x64

LE 2.50 | Visual Studio 2010 | RenderMonkey 1.82 | gDEBugger 5.8 | FX Composer 2.5 | UU3D 3 | xNormal 3.17

 

 

76561198023085627.png

Link to comment
Share on other sites

Yeah, mathematically it's not a normal.

 

But here in the picture you can see errors for different lengths as blue lines.

So as you can see longer is not more accurate actually.

The red arrow shows the best length, and the minimal error.

Ah, that's a good illustration. I like this approach.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...