PDA

View Full Version : Please help explain part of bump map demo



lucidmm
11-24-2002, 05:10 AM
In an NVidia bump mapping demo, the author uses this struct to help encode the normal map:

/* Structure to encode a normal like an 8-bit unsigned BGRA vector. */
typedef struct {
GLubyte nz, ny, nx;
GLubyte mag;
} Normal;

Then he converts a height field to a normal map like this:

nmap = malloc(sizeof(Normal)*w*h);

nx = dcy*reciplen;
ny = -dcx*reciplen;
nz = reciplen;

/* Repack the normalized vector into an RGB unsigned byte vector in the normal map image. */
nmap[i*w+j].nx = 128 + 127*nx;
nmap[i*w+j].ny = 128 + 127*ny;
nmap[i*w+j].nz = 128 + 127*nz;

nmap[i*w+j].mag = 255;

Finally, he calls this code to load the normal texture:

glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, level, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &nmap->nz);

My question is how exactly does &nmap->nz retrieve all the normal map information?


[This message has been edited by lucidmm (edited 11-24-2002).]

[This message has been edited by lucidmm (edited 11-24-2002).]

dorbie
11-24-2002, 05:19 AM
The values as you say are mapped to an unsigned byte.

When retreiving the normal map the values 0->255, conceptually produce values 0.0 to 1.0 in OpenGL internally, and these get mapped back to -1.0 to 1.0 on the way into the combiner unit.

There are modes on the way into texture combiners that can implement the required half bias and scale by two required for this type of operation. Specifically the token to look for that sets this up in your example code is GL_EXPAND_NORMAL_NV.

These and other similar operations are useful for this type of thing and other stuff like extended range rendering.


[This message has been edited by dorbie (edited 11-24-2002).]

lucidmm
11-24-2002, 05:43 AM
I understand that, but how are the normal vectors fed into glTexImage2D? The normal vector is specified by three components nx, ny, nz.

However, it seems like only the nz component is going to glTexImage2D.

JONSKI
11-24-2002, 05:55 AM
Originally posted by lucidmm:
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, level, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &nmap->nz);

My question is how exactly does &nmap->nz retrieve all the normal map information?"&nmap->nz" is like passing in "the address of the the first component of the first element of 'nmap'". In other words, I'm pretty sure passing in "nmap", "(GLubyte*)nmap", or "(GLvoid*)nmap" would accomplish the exact same thing as "&nmap->nz".

dorbie
11-24-2002, 05:56 AM
All components are packed into the same structure. In the array of normal objects each object has all the components in memory. The array will have the whole image with all the components interleaved in memory. The pointer to the first ->nz field merely addresses the first byte in memory of the packed array. The nx and ny members in that packed array are filled in the loop. It's not pretty but it will work.

[This message has been edited by dorbie (edited 11-24-2002).]

lucidmm
11-24-2002, 06:32 AM
Thanks for the help. Does anyone know for sure if just nmap will work?

Asgard
11-24-2002, 06:40 AM
It'll work, and is a bit cleaner too IMHO.

dorbie
11-24-2002, 07:30 AM
You need to cast it to a pointer to GLubyte, looks like JONSKI gave this as an example already.

[This message has been edited by dorbie (edited 11-24-2002).]