Hello everyone,
I am struggling with calculating the lightmap for my game. A level just consists of surfaces for walls/floors/ceilings (like in Wolfenstein3D).
Currently the pipeline looks as the following:
- render the scene into the depth buffer from the light source's point of view
- iterate over all surfaces (each surfaces consists of an 8x8 grid of lumels)
- for each lumel check the distance D to the light source
- find the point Q in the near plane of the light source
- transform Q into screen space and look inside the depth buffer at that position
- if depth value is less then D then lumel is in shadow
I guess that I am doing something wrong transforming Q into screen space.
// ...
float u = ((float)x + 0.5f) / lmWidth;
float v = ((float)y + 0.5f) / lmHeight;
glm::vec3 lumel = surface.vertices[0].position + u * uAxis + v * vAxis;
glm::vec3 lightLumelDir = glm::normalize(lumel - lightPosition);
// ==== EDIT: It isn't the near plane to get the actual point on the plane
// glm::vec3 planePositionWorld = lightPosition + near * lightLumelDir;
float dist = 0.0f;
glm::intersectRayPlane(lightPosition, lightLumelDir, lightPosition + near * lightNormal, nearPlane.normal, dist);
glm::vec3 planePositionWorld = lightPosition + dist * lightLumelDir;
// EDIT ====
glm::vec4 position = projection * view * glm::vec4(planePositionWorld, 1.0f);
glm::vec4 positionNDC = position / position.w;
float nx = positionNDC.x;
float ny = positionNDC.y;
if (nx < -1.0f || nx > 1.0f || ny < -1.0f || ny > 1.0f) continue;
// Screen space coordinates
float sx = ((nx + 1.0f) / 2.0f) * frameBufferWidth;
float sy = ((ny + 1.0f) / 2.0f) * frameBufferHeight;
float depth = 0.0f;
glReadPixels((int)sx, (int)sy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
// Check distance between lumel and depth value
float lumelDistance = glm::distance(lumel, lightPosition);
if (depth < lumelDistance) continue;
// light intensity calculation
// ...
Of course, without the check in point 4 I get a nicely shaded lightmap ? - without shadows :(
Thanks,
danqua