Sign in to follow this  
Deliverance

Lightmapping - light bleeding problems due to biliniear filtering and visiblity info

Recommended Posts

I have some problems when implementing lightmapping , the light bleeding artefact that is. I solved this by offseting the lightmap 1 pixel. This works well, but when I take into account visibility between lumels when calculating the intensity at each lumel, problems arise. It's like this: the lightmap texture is now offseted, I calculate intensity for all the pixels of the texture. Let's say line 0 of pixels are all occluded but the next line , line 1, contains pixels that are not occluded, this line 1 in the texture represents the line 0 of the lightmap(because is offsetted). Anyway in this case the (line 1) in the texture(line 0 of the lightmap) affects the filtering of line 0 of the lightmap, which gives incorrect results on screen. I used the words lightmap and texture up above: When I refer to texture, I mean the actual texture that contains the intensities, this contains (0..width+2)x(0..height+2) pixels, where width and height denote the with and heightof the lightmap When I say lightmap I refer to the actual part of the texture used for modulating with a surface to create the effect of lighting, that is : lines 1...height+1 and collons 1..width+1 of the texture. I hope you understand. The short question is: how do I solve the light bleeding problem and take into account visibility information between lumels(also called patches sometimes)? Please help ! [Edited by - Deliverance on August 20, 2006 6:45:46 AM]

Share this post


Link to post
Share on other sites
Hi.

Don't know if it's the answer you want but this is how I solved my bleeding issues.

First I made sure that the different charts/polygons/surfaces in the lightmap had some distance in between them. I used a distance of 2 pixels, which means every chart would have a 1 pixel border.
After I've done the actual light calculations and pixel plotting I do a postprocess on the lightmap that fill in these borders by fetching the nearest pixel which resides on a chart.
I don't know the official name for this but I call it "Edge-growing".

Some bleeding may still occur on very small surfaces but in whole this greatly reduces the bleeding.

Here is a small pic to demonstrate...



The top one is a lightmap with 0 distance between the charts.
The lower one has 2 pixel in between each chart(or 1 pixel border around each chart)

Share this post


Link to post
Share on other sites
You shouldn't need to add those extra pixels. At a guess, you're probably running afoul of the 0.5 texel offset that occurs when sampling textures.

There's also issues with anisotropic filtering and FSAA, that are mentioned in this thread: http://www.gamedev.net/community/forums/topic.asp?topic_id=410018

I'll assume you're aware of those problems, and that your problem is in properly mapping vertices to UV coords in the texture.

For simplicity, I'll only mention this along the U dimension. Same thing applies to V.

To get the lightmap coords set up properly, they need to account for (width+1) and the 0.5 texel offset.

For example, say you're trying to map a lightmap that is 8 units wide (let's say they're inches), and you want to sample the light map every inch. The map should need exactly 9 samples in U: [0] through [8], inclusive.

Assume your lightmapping algorithm assigned the texture points [10] to [18] in a texture 256 texels wide. When assigning the U coordinate to your lightmap, you need to account for the 0.5 texel offset in reading the texture samples so that the bi-lerped color value out of the texture contains only that texel. There's a good description of this in the DirectX docs:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/Directly_Mapping_Texels_to_Pixels.asp

(Though I see MS has changed the docs from the version I'm used to reading. That online version isn't as clear about diagramming the 1/2 texel offset. It explains from screen space, where you can adjust by subtracting 0.5, as opposed to fixing it in UV space, where you need to add 0.5. But doing it in screen space only works when displaying a texture as a bitmap.)

But back to mapping [10] and [18] to U coords...

The first corner should have U = (10 + 0.5) / 256
Second corner has U = (18 + 0.5) / 256

Accounting for sample count == (width + 1) and the 0.5 texel offset, there should be no bleeding of values from adjacent lightmaps in the same texture. If you're still seeing bleeding, either there's a bug in your code, or you have aniso or FSAA enabled.

I've been down this route before. If you have to add a border around the sub-rect containing the light map, there's something wrong in the code. The border will only hide the problem, which will manifest itself in other problems with the lightmaps -- especially when you need two separate lightmaps to join along a common edge when rendered. If you get this wrong, you'll have a major headache trying to figure out why there is overlap or an apparent missing row of texels where the lightmaps join up. There are lots of things that can go wrong when creating good-looking lightmaps, so it's essential you get the UVs correct.

And another tip: if your mapping of world points to lightmap points results in something that contains a fraction of a texel, round to a whole number of texels. So a 4.7 inch range should be treated as 5 so the stopping point ends on a texel. Trying to end on a fraction of a texel also causes problems when getting lightmaps to join cleanly.

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