Lightmap generation/Shadow calculation

I’m creating a simple OpenGL based generic lightmapper (by simple I mean NO radiosity). I’ve scoured forums and google, but all I could find were poorly explained, rigid lightmapper source.

The first problem I’m having is remapping the texture of a triangle. Can I use opengl’s TexGen for this, or is it more complicated?

The second thing I’m REALLY having a problem with is, as you may have guessed, finding the world position of a point on a traingle. If I do that, I can find it’s distance from the point light, and illuminate accordingly. I’ve heard someone say that I need “Barycentric coordinates.” I’ve googled it, and have a vague definition of it, but I have no idea how I would use that to find the position.

Please help me, other people seem to be able to just figure this stuff out… and it annoys me.

If you help me out, I’ll give you a cookie :wink: .

How about this http://www.humus.ca/index.php?page=3D&ID=51 ?

BTW, I’ll take chocolate chip. :smiley:

-SirKnight

If I understand you right, you want to render the scene from each lightmap texel’s center (simulate hemisphere at each fragment by cube) and so, you’d be able to approximate total incoming light at this point. Right?

If so, do it in tangent space. For each triangle in your scene figure out normal, tangent and binormal. Now, in tangent space, find a tangent space rectangle boundary for your triangle. Having done this, you can easily partition rectangle into grid you’ll later use to generate lightmap texels.
The rest is pretty straightforward, set up your camera in each of the texels you want to have in your lightmap. Render the scene to 5 sides (excluding back side) of a cube from the same point of view, but in different directions. Scene should be rendered without textures, colors etc., only lighting. Sum up the color from your 5 images sampling by regular angle value in your cube (again, which simulates hemi-sphere). And so, you have your final lightmap texel color. Do it for all of your texels and lightmap is done for you.

BTW, I’ve seen someone in this forum showed its engine ‘capable’ of doing it in ‘real-time’, thus having soft shadows…but surely this is not well suited for real-time rendering.

GL!

www.fluidstudios.com features a lightmap renderer freeware with source, good for reference.

The second thing I’m REALLY having a problem with is, as you may have guessed, finding the world position of a point on a traingle. If I do that, I can find it’s distance from the point light, and illuminate accordingly. I’ve heard someone say that I need “Barycentric coordinates.” I’ve googled it, and have a vague definition of it, but I have no idea how I would use that to find the position.
taken from a lightmapper i wrote years ago (btw my coding style has improived in the meantime :slight_smile: , gotta luv the indirection at work )

// make a tri from the 3 corners of a tri use the texcoords to define the corners of the tri
// see if point(pixelX,pixelY) is within the defined triangle
v1 = VECTOR(shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum3+0] ].u,
shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum
3+0] ].v, 0);
v2 = VECTOR(shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum3+1] ].u,
shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum
3+1] ].v, 0);
v3 = VECTOR(shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum3+2] ].u,
shadmesh[mn].mesh->tex_coords[ shadmesh[mn].mesh->triangle_groups[0].indices[trinum
3+2] ].v, 0);

				xpoints[0] = v1.x; xpoints[1] = v2.x; xpoints[2] = v3.x; 
				ypoints[0] = v1.y; ypoints[1] = v2.y; ypoints[2] = v3.y; 
				ptx = float(pixelX) / float(imageWidth);
				pty = float(pixelY) / float(imageWidth);

				if ( pnpoly(3, xpoints, ypoints, ptx, pty ) ==0 )
					continue;

				VECTOR pt( pixelX / float(imageWidth) , pixelY / float(imageWidth), 0 ); 

				float bayu, bayv, bayw, baytemp;

				baytemp =  (v2.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (v2.y - v1.y);
				bayu	= ((v2.x - pt.x) * (v3.y - pt.y) - (v3.x - pt.x) * (v2.y - pt.y)) / baytemp;
				bayv	= ((v3.x - pt.x) * (v1.y - pt.y) - (v1.x - pt.x) * (v3.y - pt.y)) / baytemp;
				bayw	= ((v1.x - pt.x) * (v2.y - pt.y) - (v2.x - pt.x) * (v1.y - pt.y)) / baytemp; 

			//	bayu = tex_coord_tri.v1 + slope1 * pixelX + slope2 * pixelY;

				Light_lineSegment.Origin =	shadmesh[mn].mesh->frames[0].verts[ prop.modelHigh->meshes[mn].triangle_groups[0].indices[trinum*3+0] ] * (bayu) +
												shadmesh[mn].mesh->frames[0].verts[ prop.modelHigh->meshes[mn].triangle_groups[0].indices[trinum*3+1] ] * (bayv) +
												shadmesh[mn].mesh->frames[0].verts[ prop.modelHigh->meshes[mn].triangle_groups[0].indices[trinum*3+2] ] * (bayw);		// w == 0

	
				if ( world.does_this_linesegment_intersect_anything(Light_lineSegment, this, mn, trinum ))
				{
					lightmapTexture[ pixelY*int(imageWidth)  + pixelX ] = 0.0;
					shadmesh[mn].has_lightmap = true;
				}

Ah, I knew I could count on you guys!

@SirKnight: Thanks for the link, this looks like it’ll help me out!

@Mickey Mouse: This seems like one of the easier ways to do it, but I don’t know what you mean by Tangent space and Binormal.

@Zed: Thanks for the source! But there are some things I am confused about. I assumed that pnpoly() checks if a point is on the plane of a triangle, but it takes 5 parameters! What does that function do?

And down where you were using the “bay” variables, it looks like you’re using cross product, and the only time I’ve seen that used is when your finding the normal of a triangle, is that what you’re doing?

Thanks everyone for your help, 4 cookies, comin’ up!

Originally posted by SirKnight:
BTW, I’ll take chocolate chip. :smiley:

Ba ha ha ha ha that is funny.
Sorry for the off topic, had to :smiley:

Originally posted by ionstream:
@Mickey Mouse: This seems like one of the easier ways to do it, but I don’t know what you mean by Tangent space and Binormal.
Take a look at this .

Originally posted by MickeyMouse:
[b]If I understand you right, you want to render the scene from each lightmap texel’s center (simulate hemisphere at each fragment by cube) and so, you’d be able to approximate total incoming light at this point. Right?

If so, do it in tangent space. For each triangle in your scene figure out normal, tangent and binormal. Now, in tangent space, find a tangent space rectangle boundary for your triangle. Having done this, you can easily partition rectangle into grid you’ll later use to generate lightmap texels.
The rest is pretty straightforward, set up your camera in each of the texels you want to have in your lightmap. Render the scene to 5 sides (excluding back side) of a cube from the same point of view, but in different directions. Scene should be rendered without textures, colors etc., only lighting. Sum up the color from your 5 images sampling by regular angle value in your cube (again, which simulates hemi-sphere). And so, you have your final lightmap texel color. Do it for all of your texels and lightmap is done for you.

BTW, I’ve seen someone in this forum showed its engine ‘capable’ of doing it in ‘real-time’, thus having soft shadows…but surely this is not well suited for real-time rendering.

GL![/b]
Hmmm…Easier said then done I suppose. :slight_smile:

Is there a working example of this anywhere? It sounds suspiciously like
something that deals with radiosity, and I don’t know anything about that.

Yes, this looks like a radiosity tutorial I have seen recently…

I’ve mostly figured out the math for the lightmapper, basically I have to remap the triangles in a planar fashion, but I am still having trouble finding the world space points…

I think that if I can find the vectors below and to the side of the new UV mapped triangle, I can multiply this by the UV of the lightmap pixel position…

Again, extensively researching this.