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 > 3D Lighting is broken - multiple libnds bugs.

#123868 - 3D_geek - Sun Apr 01, 2007 12:51 am

I've just started to play with lighting for 3D graphics - and I can't get ANYTHING to work. So I looked at the trusty 'nds-examples-20070127.tar' bundle to see what the example programs do. Several of the NeHe demos and one or two of the Misc demos seem to turn on 3D light sources, they set the light attribute on the glPolyFmt call and provide normals for simple things like cubes and such - so I presume we have (at least at some stage) gotten lighting working.

However, when I run those demos - none of them seem to show any kind of 3D lighting effect at all! Well - this perhaps explains why I'm having no luck!

So - starting at the beginning - do I have good vertex normals?

Well all of the examples have things like:
Code:

        NORMAL_PACK(0,inttov10(-1),0),
        NORMAL_PACK(0,inttov10(1),0),
        NORMAL_PACK(inttov10(1),0,0),
        NORMAL_PACK(0,0,inttov10(-1)),
        NORMAL_PACK(inttov10(-1),0,0),
        NORMAL_PACK(0,inttov10(1),0)

...as the normals for the six faces of a simple cube. NORMAL_PACK says:
Code:

#define NORMAL_PACK(x,y,z)   (((x) & 0x3FF) | (((y) & 0x3FF) << 10) | ((z) << 20))

And inttov10 (and floattov10) say:
Code:

#define inttov10(n)          ((n) << 9)
#define floattov10(n)       ((v10)((n) * (1 << 9)))

So I deduce that there are 10 bits for each component of the normal - packed into a 30 bit word...but hold on - normals are signed quantities?! According to the hardware bible: http://nocash.emubase.de/gbatek.htm#ds3dpolygondefinitionsbyvertices ...we are required to provide:
Quote:

4000484h - Cmd 21h - NORMAL - Set Normal Vector (W)
0- 9 X-Component of Normal Vector (1bit sign + 9bit fractional part)
10-19 Y-Component of Normal Vector (1bit sign + 9bit fractional part)
20-29 Z-Component of Normal Vector (1bit sign + 9bit fractional part)
30-31 Not used

Oh - oh. That's not what libnds does!

If we take a number like 1 or 1.0f (as used in ALL of the cube examples) and hand it to inttov10 or floattov10, we'll get 0x200. But that's '-0' in the DS's sign-and-magnitude setup! On the other hand, if I hand a -1 to inttov10, it'll hand me back 0xfffffe00 - which NORMAL_PACK will chop down to 10 bits by ANDing it with 0x3FF - which leaves me with 0x200 again!!! No wonder none of these programs can light up a simple cube - all of the surface normals are (0,-0,0), (-0,0,0) or (0,0,-0)...basically...Zero!!! Since (0,0,0) is not of length 1, it's not a valid normal...who knows what the hardware does with that junk?!

So none of the example programs have good normals! They can't ever have had proper lighting working?!?

There seems to be a similar problem in the packing of texture coordinates - same deal. with sign-and-magnitude representations. The difference here is that the error is less noticable because relatively few models use negative or maximum-possible-value texture coordinates.

Has any of this stuff ever been used for real? Didn't anyone ever think to worry about why none of the lighting works in any of the stock examples?

When I fix this problem in my own code - I still don't get any 3D lighting - but since it appears that nobod tested this stuff properly - that's not really a surprise!

#123870 - tepples - Sun Apr 01, 2007 1:19 am

3D_geek wrote:
If we take a number like 1 or 1.0f (as used in ALL of the cube examples) and hand it to inttov10 or floattov10, we'll get 0x200. But that's '-0' in the DS's sign-and-magnitude setup!

Since when is anything on the DS in sign-and-magnitude form?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#123872 - 3D_geek - Sun Apr 01, 2007 1:28 am

tepples wrote:
3D_geek wrote:
If we take a number like 1 or 1.0f (as used in ALL of the cube examples) and hand it to inttov10 or floattov10, we'll get 0x200. But that's '-0' in the DS's sign-and-magnitude setup!

Since when is anything on the DS in sign-and-magnitude form?


Are you saying that this document is wrong?

http://nocash.emubase.de/gbatek.htm#ds3dpolygondefinitionsbyvertices

But no matter whether it's sign/magnitude or two's complement, the fact that:

a) The example programs use inttov10(1) and inttov10(-1) as normal values.
b) These two numbers produce IDENTICAL bit patterns after smooshing them through NORMAL_PACK.

....means that there is a problem.

#123885 - M3d10n - Sun Apr 01, 2007 4:48 am

The teapot display list example I have on my drive seems to be properly lit. I'm using an old libnds version, so maybe it got broken on recent releases?

#123894 - DekuTree64 - Sun Apr 01, 2007 6:44 am

3D_geek wrote:
a) The example programs use inttov10(1) and inttov10(-1) as normal values.

Yes, that is bad. The 1.9 bit normal format can't reach a full positive 1. Probably would be best to make a named constant for the maximum value (just use inttov10(1) - 1).
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#123925 - 3D_geek - Sun Apr 01, 2007 5:41 pm

M3d10n wrote:
The teapot display list example I have on my drive seems to be properly lit. I'm using an old libnds version, so maybe it got broken on recent releases?


Yes - you're right - that one is correctly lit with the latest stuff too. It's a nice curvey objecf - not a cube or anything - so it probably doesn't have any 1.0 or -1.0 normal components.

Thanks!

#123927 - 3D_geek - Sun Apr 01, 2007 6:01 pm

Another reason many of the lighting examples aren't working is because that same inttov10/floattov10 problem occurs in the glLight call. Hence all of our light sources are someplace where they shouldn't be....I havn't yet quite figured what this does - but I suspect it's killing lighting somehow.

#123928 - silent_code - Sun Apr 01, 2007 6:39 pm

lighting works fine in my demo (http://forum.gbadev.org/viewtopic.php?t=12873). i had all four lights enabled and working well, though i thought one light may be enough for that simple scene. ;^D

happy coding.

ps: one doesn't question tepples. ;^p

#123951 - 3D_geek - Mon Apr 02, 2007 12:34 am

silent_code wrote:
lighting works fine in my demo (http://forum.gbadev.org/viewtopic.php?t=12873). i had all four lights enabled and working well, though i thought one light may be enough for that simple scene. ;^D


When I fix my normals so inttov10 and floattov10 are replaced with code that clamps the (1,0,0) type of cases - and do the same thing with glLight positions - my lighting works OK too. This is likely to be a common problem in application programs though - especially if the example programs don't get it right.

It's well enough to say "Well, use floattov10(0.97,0,0) in those cases - but very often the normal comes about through some kind of calculation from the polygon vertices - so it'll be wise to scale down the vector by a factor of 0.97 everywhere just to be sure. Personally I'm going to put a clamp in my version of the inttov10/floattov10 code because roundoff errors could still result in overflow - and the consequences of that are rather serious. Fortunately, I don't use those calls inside any inner loops so the extra cost is negligable in my application.