Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Noisy lightmaps #10

Closed
braddabug opened this issue Jul 9, 2017 · 8 comments
Closed

Noisy lightmaps #10

braddabug opened this issue Jul 9, 2017 · 8 comments
Assignees

Comments

@braddabug
Copy link

I'm having a weird problem that I can't figure out. You can see a screenshot and the generated lightmap here: https://imgur.com/a/2NqIT

It's like some of the samples are just wrong (usually black instead of grayish, but sometimes white), as if depending on the hemisphere orientation the light is either visible or not visible, but that's wild speculation. I tried turning off interpolation to render all the hemispheres, but that didn't help.

@ands
Copy link
Owner

ands commented Jul 9, 2017

Hi,

What do you write into the alpha channels in your own surface fragment shaders? (should be 1.0 for front faces)
Do you maybe clear the framebuffer on your own? Or change the target framebuffer/viewport/scissor rect?
Do you modify the matrices before multiplying them with the vertex positions?
What are your lmCreate parameters and api call order?

Cheers :),
Andreas

@ands ands self-assigned this Jul 9, 2017
@braddabug
Copy link
Author

My code is based on the example, so the shaders are the same. And I can't find anywhere that I'm clearing the framebuffer or changing anything before drawing.

My call to lmCreate() looks like this:

lm_context *ctx = lmCreate(
		64,               // hemisphere resolution (power of two, max=512)
		0.01f, 200.0f,   // zNear, zFar of hemisphere cameras
		0, 0, 0, // background color (white for ambient occlusion)
		0, 0.00f);        // lightmap interpolation threshold (small differences are interpolated rather than sampled)
						  // check debug_interpolation.tga for an overview of sampled (red) vs interpolated (green) pixels.

Then I'm calling lmSetTargetLightmap(), then lmSetGeometry(), then the lmBegin()/lmEnd() loop.

The full source is here: https://github.com/braddabug/thegame/tree/master/Tools/LightmapTool

It's got to be some little thing I'm doing wrong. I checked with Valgrind on Linux and it didn't report anything. OpenGL doesn't complain about anything either.

@ands
Copy link
Owner

ands commented Jul 9, 2017 via email

@ands
Copy link
Owner

ands commented Jul 10, 2017

Hey :)
First I thought that the noise looked very random, but after building and running your tool I quickly realized that you are using a very tiny light source. So, the noise is just a very severe undersampling artifact.
I actually got ok-ish results when increasing the hemisphere rendering resolution. Try these parameters:

lm_context *ctx = lmCreate(
512, // hemisphere resolution (power of two, max=512)
0.01f, 200.0f, // zNear, zFar of hemisphere cameras
ambientRed, ambientGreen, ambientBlue, // background color (white for ambient occlusion)
3, 0.01f);

It will be slower and there's still some minor noise on some wall parts.
You can easily get rid of noise artifacts (and thus improve performance, because you don't need such a high hemisphere rendering resolution) by using larger light sources, if applicable.

Here's a shot with two bounces:
Indirect Light

@braddabug
Copy link
Author

Thanks! Now that I think about it that makes perfect sense.

The tiny point light will eventually become a directional "sun" light. Maybe it'd be best to investigate representing the entire sky as an HDR floating-point cubemap, that way aliasing becomes less of an issue since the cubemap can easily be filtered/smoothed. I think.

@jpcy
Copy link

jpcy commented Jul 11, 2017

You could ray trace the directional sun light using Embree. Use the lightmapper rasterizer to get the worldspace position of each luxel, then trace a ray in the direction of the sun to see if it's occluded. For smoother shadows, take multiple samples with jittered sampling positions and average them. Then run the lightmapper to get bounce lighting.

@ands
Copy link
Owner

ands commented Jul 11, 2017

If you want to use this lib for indirect lighting, you could also render your scene with the usual direct scene lighting during baking (a static shadow map, materials, point/directional/spotlights, etc.)

@braddabug
Copy link
Author

braddabug commented Jul 12, 2017

I think that will work. I modified my code to do a initial pass where I shoot a ray from each texel to the light, and that calculates pretty nice direct lighting. Then I feed that in to the emissive texture and start the indirect lighting passes. It looks quite a bit nicer. Practically no noise!

I did have to modify lightmapper.h to get things like the lightmap texel position (world coords and texel coords) and normal since the contents of lm_context are hidden. I just added this function:

void lmTexelInfo(lm_context* ctx, float* outWorldPos, float* outDirection, int* outTexelCoord, int* hemisphereSideIndex)
{
	if (outWorldPos)
	{
		outWorldPos[0] = ctx->meshPosition.sample.position.x;
		outWorldPos[1] = ctx->meshPosition.sample.position.y;
		outWorldPos[2] = ctx->meshPosition.sample.position.z;
	}

	if (outDirection)
	{
		outDirection[0] = ctx->meshPosition.sample.direction.x;
		outDirection[1] = ctx->meshPosition.sample.direction.y;
		outDirection[2] = ctx->meshPosition.sample.direction.z;
	}

	if (outTexelCoord)
	{
		outTexelCoord[0] = ctx->meshPosition.rasterizer.x;
		outTexelCoord[1] = ctx->meshPosition.rasterizer.y;
	}

	if (hemisphereSideIndex)
	{
		hemisphereSideIndex[0] = ctx->meshPosition.hemisphere.side;
	}
}

EDIT: I tweaked the code a little bit. I wanted the hemisphere side index, but I guess I was getting the hemisphere index instead.

@ands ands closed this as completed Sep 10, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants