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
    Commented Jul 8, 2021 at 16:04

1 Answer 1

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
    Commented Jul 8, 2021 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
    Commented Jul 8, 2021 at 17:55
  • \$\begingroup\$ Thanks for your help! \$\endgroup\$
    – Shikhali
    Commented Jul 8, 2021 at 19:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .