ands / lightmapper

A C/C++ single-file library for drop-in lightmap baking. Just use your existing OpenGL renderer to bounce light!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?

commented

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 :)