gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Lighting and normals

#108370 - Rajveer - Wed Nov 08, 2006 4:49 am

I have an array of polygons with their normals which I store as a fixed point number (for calculations). I want to use these normal data for hardware lighting of my mesh too. I have a loop which I call:

Code:
int n = 0;
   for(n = 0; n < polylimit; n++)
   {
         glBegin(GL_TRIANGLES);

glNormal3f((f32tofloat(Level1Poly[n].normal[0])),(f32tofloat(Level1Poly[n].normal[1])),(f32tofloat(Level1Poly[n].normal[2])));

         glTexCoord2t16(Level1Poly[n].tex0[0], Level1Poly[n].tex0[1]);
         glVertex3v16(Level1Poly[n].vertex0[0],Level1Poly[n].vertex0[1],Level1Poly[n].vertex0[2]);

         glTexCoord2t16(Level1Poly[n].tex1[0], Level1Poly[n].tex1[1]);
         glVertex3v16(Level1Poly[n].vertex1[0],Level1Poly[n].vertex1[1],Level1Poly[n].vertex1[2]);

         glTexCoord2t16(Level1Poly[n].tex2[0], Level1Poly[n].tex2[1]);
         glVertex3v16(Level1Poly[n].vertex2[0],Level1Poly[n].vertex2[1],Level1Poly[n].vertex2[2]);
         glEnd();
   }


However I dont get the results I want, infact its not lit at all, and after testing I think its a problem with the f32tofloat part. When I replaced it with a bitshift >>12 it gave me screwed up lighting. I dont think theres a glNormal3v16 function so any tips?

#108435 - M3d10n - Wed Nov 08, 2006 8:05 pm

I'm pretty sure you need to define a normal for each vertex, in the same way you do the texture coordinates.

Also, you need to set the polygon format to enable the lights, as well as setup some lights. If you're using devkitpro, check some of the 3D examples to see how you do that.

#108442 - Payk - Wed Nov 08, 2006 9:12 pm

Well 2 things.
Each vertex needs a normal.
Second: For storing normals i recommand v16.
Each of the 3 normal atribute is between 0 and 1.
v16 is 100% compatbile to f32. But not vice versa.
That means v16 normals can be used with f32 functions as well.
f32 is like v16 but with more bits before the fixed point. So v16 is perfect for normals ;)

Dont use normal3f. It needs float...its evil what you are doing...you convert from f32 to float and the gl function converts float to v10....
here is a code snippped what that funcion does:
Code:
//---------------------------------------------------------------------------------
void glNormal3f(float x, float y, float z) {
//---------------------------------------------------------------------------------
   if(x >= 1 || x <= -1) x *= .95;
   if(y >= 1 || y <= -1) y *= .95;
   if(z >= 1 || z <= -1) z *= .95;

   glNormal(NORMAL_PACK(floattov10(x), floattov10(y), floattov10(z)));
}


and here is another snipped...
thats what happens when converting to v10 from a float:
Code:
#define floattov10(n)        ((v10)((n) * (1 << 9)))


So what to do now?
store that normals in v16. For that u can use floattov10(n).
4 bits will be unused...but that dosnt hurt that much.
When you got your preconvertet normals just call:
glNormal( NORMAL_PACK((v10)x,(v10)y,(v10)z) ); or something.
It will be MUCH faster.

#108453 - Rajveer - Wed Nov 08, 2006 11:51 pm

Sweet, cheers for the help guys!

1) Lights are switched on, they're working for my ship model (when I rotate my ship the lighting changes). Which brings me onto the second part.

2) Are you guys sure you need one normal per vertex? I thought that was if you wanted a smooth shading (per-vertex shading), whereas if you want flat polygon shading you dont call a normal per vertex but per face (what I'm doing with my ship which works)

I've changed my code so that normals are stored as v16. But the lighting still doesnt work properly, now the majority of polygons on this mesh are dark with a few bright ones with no consistency. When I use glNormal(NORMAL_PACK... do I have to have the normals in v16 or v10? Would it even matter? :S

In short:
I'm using v16s and I call

Code:
glNormal(NORMAL_PACK((v10)Level1Poly[n].normal[0],(v10)Level1Poly[n].normal[1],(v10)Level1Poly[n].normal[2]) );


where Level1Poly[n].normal...are stored as v16 normals

#108458 - Payk - Thu Nov 09, 2006 12:37 am

It wouldnt matter.
The first for bits(or last in fact) would be ignored. as i said, normals are going from 0 to 1. if you take all 3 combonets together its one. So the 4 bits arent nececary....why sending them then?
Anyway, your right, for smoothshading just call one per vertex. for flat, one per poly.

And it realy doesnt matter if v16 or v10...if you store informations , u can do it bytewhise....so even a v10 is 16Bit. a v16 is 16bit too. The fixed point is on same place. and on same place like in f32....u can use them backward. means on a f32 function, u can overgive a f32,v16 or v10.
on a v16 u can over give v10 or v16. on a v10 you can overgive all to, but just 10bits will be reconized (afaik)....I used v16. it makes most sence since its smaller then f32 and has same functionality (floattov16,inttov16...blub)