Lighting

Feb 18, 2010 at 9:09 AM

I've started playing around with point lights and they don't seem to be working correctly for me.  In this screenshot I have a full tube surface where the front opening is centered on the origin, and one point light also on the origin.  I would expect a point light to send light out in all directions but it only appears to be lighting the bottom half of the tube.  I added a normal map in another test and it was also showing weird results where the light didn't seem to reflect properly from one side in some cases or appeared "inside out".  From my investigations I'm suspecting this has something to do with the winding order of the vertices because the points flip as I draw around the surface, but I tried reversing the winding order (expecting the light switch round and work on the top instead of the bottom) and it didn't seem to have any effect at all.  Spent quite a bit of time on this now but its got me stumped.  Any idea what's going on here?

Coordinator
Feb 18, 2010 at 10:19 AM

Did you set your vertices' normal data appropriately? For an example of how this can be done algorithmically, look starting on line 48 of TerrainPatchGeometry.cs. If you want normal mapping, you must make sure to use vertices that have appropriate Binormal and Tangent data as well.

Feb 21, 2010 at 3:56 AM

Once again you're spot on.  I'd copied some of the code from QuadGeometry so it was setting the normals, but it was setting them to all be Vector3.Up.  Makes perfect sense now why it appeared as thought the light was only coming from the top.  So I've fixed that up to make the normals perpendicular to the surface of each quad and the whole tube is being lit.  I now also understand what the tangent and binormals are, although I'm not sure I'm calculating any of these perfectly yet.

Besides that I think I need to confirm I'm actually applying the values right first because setting them doesn't seem to have any effect atm.  First I'm creating the vertices by passing a vertex format of "PositionNormalTextureBinormalTangent" to VertexFactory.CreateVertices (instead of "PositionNormalTexture").  Then once I've got the IVertices (verts) I have to call verts.SetUserDefined("Tangent", ...) and verts.SetUserDefined("Binormal", ...) to apply the values.  Is this the right way to go about it or should I maybe be making my own implementation of IVertices?

 

Coordinator
Feb 21, 2010 at 4:46 AM

You are doing things correctly by passing "PositionNormalTextureBinormalTangent" and using the SetUserDefined method. However, these values are only used with the normal mapping effect and with the appropriate parameters set.

As better checking in the future, I've made invalid SetUserDefined calls to throw an ArgumentException.

Coordinator
Feb 21, 2010 at 4:50 AM

Disregard the note about throwing exceptions. I decided not to do this as it is against the intent of the Vertices abstraction.

 

Feb 22, 2010 at 8:36 AM
bryanedds wrote:

Disregard the note about throwing exceptions. I decided not to do this as it is against the intent of the Vertices abstraction.

 

So are you saying that the Vertices abstraction is supposed to silently ignore attempts to set a user-defined field that doesn't exist?  That sounds like a debugging nightmare waiting to come true.  I'm sure there's a good reason that I'm just not seeing yet, but from where I'm sitting atm I'd like some confirmation that I've got the field names correct.  At this point I have no idea where to find out what those should be called so I just guessed at them.  Then when they didn't seem to be having any effect I started wondering if I was even applying the values to anything and had no way to confirm one way or the other.  Maybe you could return a bool result from the SetUserDefined function?  My gut feeling is that it should return an exception like you suggested, but at least a result would give a way to check.

BTW I'm using oxNormalMapped.fx with an additional normal texture created by CrazyBump so I'm pretty sure I have everything I need apart from the correct vertex data.  I have seen *some* of the normal mapping working on certain panels and from certain angles.  Haven't had another chance to work on the normal/tangent/binormal calcs yet.  I've read plenty of info.  Just need to work out how to apply it correctly in my specific situation.  Hopefully have another go at it l8tr tonite.

Feb 22, 2010 at 10:32 AM

Made some good progress on this tonite.  Here's another screenshot.  In this shot I have a white diffuse color and red specular.  For the first time I'm actually seeing patches being obscured from the light source properly so that's a good sign that the normals are correct.  The one bit that doesn't seem quite right is the specular color.  I've moved the light back to Z -20 so you can see how it's only showing the highlight between the light source and the camera, not behind the light away from the camera.  Is this actually correct or does this still indicate something wrong with the tangent and/or binormal?

 

Coordinator
Feb 22, 2010 at 11:01 AM
Kermitt wrote:
bryanedds wrote:

Disregard the note about throwing exceptions. I decided not to do this as it is against the intent of the Vertices abstraction.

 

So are you saying that the Vertices abstraction is supposed to silently ignore attempts to set a user-defined field that doesn't exist?

This is correct. The intent is to allow one block of code to create any type of geometry. If it would be helpful, I could add a boolean parameter to enable throwing if the field doesn't exist or some such option.

Thoughts?

Feb 22, 2010 at 11:19 AM

After changing the diffuse/specular to gray/white this is actually looking pretty good.  I can clearly see the point light reflecting off the wall so it's obvious where it is even though u can't see the actual light source.  So I think I've cracked this one.

For the SetUserDefined function... I don't really understand why you wouldn't just throw exceptions anyway, but all was looking for was a way to confirm if the field existed so a boolean parameter would do the job fine.