Sign in to follow this  
spek

Making lightMap texture coordinates

Recommended Posts

spek    1240
Hi, Everyone who has made a lightMap probably knows that you need to define texture coordinates for all your polygons. The difficult part is that the polygon may not overlap each other, and you want to map them efficient of course (that means as less as possible unused space). My question is, how to do that? I did the first part by making groups of polygons that belong to each other, and defining their primary axis for the projection. But now I have to lay down the puzzle. How to calculate the most efficient position/scale/rotation for each group? Notice that the group shapes could be anything. Ussually it are rectangle planes, but more complex shapes are their as well. Greetings, Rick

Share this post


Link to post
Share on other sites
hplus0603    11347
That's known as the "bin packing" problem, and is generally an NP-complete problem (i e, with current theory, you can't know unless you try all the possible variations).

You can google for terms such as "mesh parameterization" to get some research on how to generate reasonable UV mappings automatically.

If you already have clusters, and the only problem is to lay them down in the texture, then I would quantize each cluster to a power of two along each size, and then place them in available space in order from biggest to smallest. When the space in the first light map runs out, start a new one. You can scale the light map down slightly along some dimension if you find that it'll take, say, 270 texels to get your ideal texel density along a specific dimension -- scale it down to 252 in that case.

Also, make sure that you generate sufficient borders around your light maps to avoid filtering problems. If you store a value for each pixel for whether it's been "lit" or not, then you can run a few passes of "if this pixel hasn't been lit, then make it the average of its lit neighbors (if any), and if so, set the 'lit' bit" to generate sufficient bordering.

When allocating sub-spaces from the light map, a quad tree is often useful to figure out what the remaining free space is.

Share this post


Link to post
Share on other sites
Kwizatz    1392
I am currently working on lightmap generation myself, I found this article regarding how to generate the UVs for the lightmap, seems pretty straight forward.

I am experimenting with PovRay and MegaPov in order to render the actual lightmaps (I figure there is no need to reinvent the wheel when a full featured wheel is already available for free [smile]).

Share this post


Link to post
Share on other sites
Stanza    144
The best reference I've seen for packing light maps is to be found at
http://www.blackpawn.com/texts/lightmaps/

This is almost the same approach I use for my system. The only significant difference is that I rotate all lightmaps so the longest axis is along U. It can help significantly when there are a large number of very long, narrow rects.

Kwizatz already pointed to one article on Flipcode. Check around that site, there's several more good intro lightmap articles. Sadly, you'll need to do it page by page through the list of articles -- attempting to google will turn up a huge number of forum links that don't work, since the sight is shut down. Thankfully the articles are still there. At least for now.

Sounds like you're just starting off with light mapping, so I'll mention a few things to keep in mind, since I had to learn them the hard way.

... remember that when textures are sampled, it's done offset by 0.5 texels. You need to account for that when setting texture coords, otherwise you'll sample off the edge of a sub-rect, and have problems getting the lightmaps to look correct at the edges, especially then two tris from different sub-rects join along a common edge.

... make sure your sub-rect dimensions are (n+1). If you're sampling at 1-foot intervals, for example, an 8-foot long wall needs 9 samples.

... mip-mapping and lightmaps do not mix well. Avoid mip-mapping, unless you're explicitly creating them yourself (but I'd still suggest avoiding mip-mapping entirely, or going down no more than 1 or 2 layers). Never let the texture loader routines mipmap for you.

... never compress lightmaps. It's almost always going to add unwanted artifacts.

... odds are pretty darned good that if any kind of filtering is being applied to the lightmap, the texture sampler will sample outside the bounds of the sub-rects, producing light/dark flickering at the edges when rendered. This includes aniso and FSAA. Different hardware exhibits different results. I've heard centroid sampled hardware suffers from this less, but haven't worked with it directly. Manually disable aniso for the texture sampler reading from the lightmap (and hope the user hasn't forced it on at the driver level). The only reliable way to prevent this is to pass min/max values down to a custom shader and clamp UVs before sampling, but that means 4 extra values to store in each vertex, and then along the internal memory bus to the pixel shader, which hurts performance. If you go that route, try to pack them into 16- or even 8-bit values.

... some places recommend adding a 1+ pixel border around each sub-rect. Don't bother. If you're generating your sub-rects properly, this isn't necessary. Just account for the (n+1). If you think you need to add more to make things look right, you're either getting your UVs set up wrong, or running afoul of the aniso/FSAA sampling problem. And borders won't prevent the aniso/FSAA problem, only minimize it a little. At sharp angles, aniso can easily pull samples from halfway across the texture buffer, so no amount of bordering can completely prevent the problem (short of storing each rect in a completely separate texture).

Share this post


Link to post
Share on other sites
spek    1240
Thank you all for the tips!

I wrote a radiosity generator and used the lightMap coordinates from LightWave. But those coordinates sucked (because of shared vertices). I always ended up unwelding points for hours, so I decided to write my own generation code. I think I have that works now, although i haven't been able to test it yet. My head is full of alcohol now, so I better not judge the results now. Giving all polies proper coordinates and an unique place isn't that hard, but putting them efficiently is another story. Well, i have the tips from you guys, so i'd better start coding further. Thanks!

Rick

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this