Can I decide which lightmap gets baked?
Raildex opened this issue · comments
I have several meshes. Each mesh has it's own unique lightmap.
I want to bake lighting for each mesh separately, but shadows of other meshes should be visible on the currently baked lightmap.
Can lightmapper do this?
Hey @Raildex,
yes, you can do this with lightmapper.
As the readme states, this is an example core loop to bake lightmaps:
for (int b = 0; b < bounces; b++)
{
// render all geometry to their lightmaps
for (int i = 0; i < meshes; i++)
{
memset(mesh[i].lightmap, 0, sizeof(float) * mesh[i].lightmapWidth * mesh[i].lightmapHeight * 3); // clear lightmap to black
lmSetTargetLightmap(ctx, mesh[i].lightmap, mesh[i].lightmapWidth, mesh[i].lightmapHeight, 3);
lmSetGeometry(ctx, mesh[i].modelMatrix,
LM_FLOAT, (uint8_t*)mesh[i].vertices + positionOffset, vertexSize,
LM_NONE , NULL, 0, // optional vertex normals for smooth surfaces
LM_FLOAT, (uint8_t*)mesh[i].vertices + lightmapUVOffset, vertexSize,
mesh[i].indexCount, LM_UNSIGNED_SHORT, mesh[i].indices);
int vp[4];
mat4 view, proj;
while (lmBegin(&ctx, vp, &view[0][0], &proj[0][0]))
{
// don't glClear on your own here!
glViewport(vp[0], vp[1], vp[2], vp[3]);
drawScene(view, proj);
printf("\r%6.2f%%", lmProgress(ctx) * 100.0f); // don't actually call printf that often ;) it's slow.
lmEnd(&ctx);
}
}
// postprocess and upload all lightmaps to the GPU now to use them for indirect lighting during the next bounce.
for (int i = 0; i < meshes; i++)
{
// you can also call other lmImage* here to postprocess the lightmap.
lmImageDilate(mesh[i].lightmap, temp, mesh[i].lightmapWidth, mesh[i].lightmapHeight, 3);
lmImageDilate(temp, mesh[i].lightmap, mesh[i].lightmapWidth, mesh[i].lightmapHeight, 3);
glBindTexture(GL_TEXTURE_2D, mesh[i].lightmapHandle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mesh[i].lightmapWidth, mesh[i].lightmapHeight, 0, GL_RGB, GL_FLOAT, data);
}
}
Let's ignore the bounces loop and the postprocessing for now and assume we only want one single light bounce.
With lmSetTargetLightmap
and lmSetGeometry
you set what you want to bake to (the output mesh & lightmap).
So you decide which lightmaps and geometry you want to bake/update.
You also have full control of the input (e.g. lights/emissives and shadow casters) by what you decide to render between lmBegin
and lmEnd
.
For better understanding of what is happening, the loop
while (lmBegin(&ctx, vp, &view[0][0], &proj[0][0])) { ... }
will simply traverse the surface of your mesh that you set by lmSetGeometry
.
At each point on the mesh, it takes a sample of the environment by rendering a hemisphere/hemicube of the scene around it. The resulting scene render at that position is then integrated down to one single pixel value, which is then written out to the lightmap at the corresponding UV coordinates.
I hope this helps :)
Thanks, that explains a lot :)