Fitting a lightmap correctly on a polygon

I have a problem correctly mapping lightmaps. For my software renderer it works perfectly but I’m having problems finding the right mapping under OpenGL. The problem has to do with borders visible around the lightmaps. First note that currently my lightmaps are all packed in a larger ‘super-lightmap’ but this problem was also there before I did this optimization.

I will explain with an example. Assume I have a rectangular polygon which is texture mapped from 0,0 to 1,1 (in uv space). I also have an associated lightmap of 16x16 (just an example) size. This lightmap is part of a bigger super-lightmap (usually 256x256 texels). Every lumel in the lightmap defines the lighting conditions at a corner of a texel block (of usually 16x16 texels). So with a lightmap of 16x16 we actually have 15x15 blocks of 16x16 texels in the texture. And every 16x16 texel block should be colored according to the neighbouring lumels (lightmap values).

The correct mapping to do this would be (ignoring offsets and scaling for super-lightmap at this time):

lm_scale_u = (lm_width-1) / (high_u-low_u);
lm_scale_v = (lm_height-1) / (high_v-low_v);

In the example above this would be:

lm_scale_u = 15 / 1;
lm_scale_v = 15 / 1;

I can see that this is the correct formula because the lightmaps of neighbouring polygons are correctly aligned even if they have different size. HOWEVER! There are borders visible around the lightmaps and they are really ugly. I assume that they are caused by OpenGL sampling pixels from outside the lightmap boundaries. The texture environment for the super-lightmap is set as follows:

glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Any idea how I can solve this problem?

Greetings and thanks in advance,


Jorrit Tyberghein: Project Manager of Crystal Space: Open Source 3D Engine http://crystal.linuxgames.com

You see filtering including the texture border color.

Try OpenGL 1.2’s GL_CLAMP_TO_EDGE instead of GL_REPEAT for the individual lightmaps.

GL_NEAREST for the filters would also cancel filtering of the texture border colors but but probably looks ugly

For the super-lightmap with linear filtering you’ll have to add a border around each sub-lightmap which replicates the outmost lumels (I like that term ).
Means in 16x16 sub-lightmap the inner 14*14 is the lightmap and the border around it allows for linear filtering without touching wrong colors.
Adjust your texture coordinates accordingly.
This is not going to work with mip-maps.

Originally posted by Relic:

For the super-lightmap with linear filtering you’ll have to add a border around each sub-lightmap which replicates the outmost lumels (I like that term ).
Means in 16x16 sub-lightmap the inner 14*14 is the lightmap and the border around it allows for linear filtering without touching wrong colors.
Adjust your texture coordinates accordingly.

I was afraid that was going to be the answer. This means that I either have to do a difficult rewrite of my lightmap generator in order to generate lightmaps differently or else add the borders at run-time. Keep in mind that dynamic lights can alter the lightmaps in a dynamic way. This complicates matters… Well I’ll see what I’ll do.

Thanks for the answer.

Greetings,

I’m not sure this will work, but can’t you just offset the tex coords 0.5 lumels “into” the triangle?

Originally posted by harsman:
I’m not sure this will work, but can’t you just offset the tex coords 0.5 lumels “into” the triangle?

Well that will scale the lightmap. i.e. the lightmap will be mapped slightly smaller on the underlying polygon. As such this would not be such a big problem were it not that adjacent polygons might scale differently. i.e. imagine a big polygon sitting next to a small polygon. Both have a lightmap. A shadow which is visible on both lightmaps should be aligned so that the shadow smoothly goes from one lightmap to the other. But if you scale them half a pixel then the relative scale for the larger lightmap will be bigger than for the smaller lightmap and they will not align.

Greetings,

Actually, it’ll be bigger, and since you’re currently seeing borders, it samples from a too big area anyway right? Maybe I’m just stupid but won’t this work if your lumel sampling rate is constant in world space (within the tiled super lightmap)? Reading your original post I realize it probably isn’t since you said each lumel usually is 16^2 texels and texels density typically isn’t constant. But if you organize the lightmaps so that all the parts that share edges have the same sampling rate (in WS), then shifting a lumel is just shifting in WS, which shouldn’t vary with polygon size. And since you just shift half a lumel, the corner points will be the same color, except the blerping won’t sample at the lumels not belonging to the polygon. Clamping tex-coords is probably simpler though. That or using border pixels.