0
\$\begingroup\$

I'm trying to render a scene using multiple point light casting shadows. Currently, If I have more than 1 point light, shadows are wrong.

I'm drawing to FBO with a depth cubemap attached to it and in geometry shader for every point light I emit vertices to each face of the cubemap.

//Geometry shader
out vec4 v_FragPos;

void main()
{
    for (int pl = 0; pl < u_PointLightsSize; ++pl)
    {
        for (int face = 0; face < 6; ++face)
        {
            gl_Layer = face;
            for (int i = 0; i < 3; ++i)
            {
                v_FragPos = gl_in[i].gl_Position;
                gl_Position = u_PointLights[pl].ViewProj[face] * v_FragPos;
                EmitVertex();
            }
            EndPrimitive();
        }
    }
}

u_PointLights is an array of PointLight structs

struct PointLight
{
    mat4 ViewProj[6];
    vec3 Position;

    vec3 Ambient;
    vec3 Diffuse;
    vec3 Specular;
    float Distance;
};

And my fragment shader looks like this

in vec4 v_FragPos;
const float g_FarPlane = 10000.f;

void main()
{
    float minDistance = g_FarPlane;
    for (int i = 0; i < u_PointLightsSize; ++i)
    {
        float distance = length(v_FragPos.xyz - u_PointLights[i].Position);
        if (distance < minDistance)
            minDistance = distance;
    }
    minDistance /= g_FarPlane;
    gl_FragDepth = minDistance;
}

Can anyone tell what I'm doing wrong? If I use one point light, shadows are fine.

\$\endgroup\$
1
  • \$\begingroup\$ Do I understand correctly that you're trying to compose the depths of objects from multiple different point lights into a single cube map simultaneously? That... really would not make any sense at all, but it's the only interpretation I can form from the code you've shown here. \$\endgroup\$
    – DMGregory
    Jul 8 at 16:04
0
\$\begingroup\$

Consider two point lights on either side of a wall. What you want is that the east light has a shadow caster to the west, and the west light has a shadow caster to the east.

If you try to render them into the same depth cube map simultaneously, you will end up with a depth map that thinks there's a wall casting shadows close to the light on both the east and west sides.

So this idea of rendering all of your lights into one cube map in a single pass is simply not feasible.

What you can do instead is this:

  • For each light
    • Render a depth cube map from its perspective
    • Shade [the relevant parts of] your scene with that light and that cube map
    • Clear the cube map before proceeding to the next light

Since light is additive, you can sum it up in multiple passes like this, whether using forward or deferred rendering.

\$\endgroup\$
3
  • \$\begingroup\$ Do I need to do smth like this? 1) Render my scene to FBO without any shadows. 2) Render a depth cubemap. 3) Pass FBO's color attachment to other shader that will shade it 4) Clear a depth cubemap. 5) Repeat from (2) for each light \$\endgroup\$
    – Shikhali
    Jul 8 at 17:52
  • \$\begingroup\$ Something like that. Your first render pass would be done without any shadowed lights, rather than "without any shadows". ie. if a light need shadows, you do not render it until you have its shadow map. You don't retroactively carve shadows into light you've already rendered. \$\endgroup\$
    – DMGregory
    Jul 8 at 17:55
  • \$\begingroup\$ Thanks for your help! \$\endgroup\$
    – Shikhali
    Jul 8 at 19:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.