10

I have implemented the basic shadow mapping algorithm but it works correctly with only one light.

I want to render a scene with two following point lights :

  • Light_1 - position : vec3(-8.0f, 5.0f, 8.0f), direction : vec3(1.3f, -1.0f, -1.0f)
  • Light_2 - position : vec3(8.0f, 5.0f, 8.0f), direction : vec3(1.3f, -1.0f, -1.0f)

If I render separately the two lights I have the following results:

Rendering with Light_1 :

enter image description here

Rendering with Light_2 :

enter image description here

But the two light together it looks like this :

enter image description here

As you can see the first shadow seems to be rendered correctly, but it is below the shadow of the light_2 which is not correct. To sum up the situation I have the texture of my box which is bound to the texture unit 0. The shadow depth texture is bound from the texture unit 1 and if there are more than one depth texture (so at least two ligths, like in this example), there are bound to the texture unit 1 + 1 (GL_TEXTURE1 + 1). Here's the code that represent what I said :

for (int idy = 0; idy < this->m_pScene->getLightList().size(); idy++)

[...]

Light *light = this->m_pScene->getLightList()[idy];
FrameBuffer *frameBuffer = light->getFrameBuffer();

glActiveTexture(GL_TEXTURE1 + idy);
glBindTexture(GL_TEXTURE_2D, frameBuffer->getTexture()->getTextureId()); //To unbind

shaderProgram->setUniform(std::string("ShadowMatrix[").append(Convertor::toString<int>       (idy)).append("]").c_str(), this->m_pScene->getLightList()[idy]->getBiasViewPerspectiveMatrix() * modelMatrix);
                    shaderProgram->setUniform(std::string("ShadowMap[").append(Convertor::toString<int>(idy)).append("]").c_str(), (int)idy + 1);

It corresponds in our case to :

shaderProgram->setUniform("ShadowMatrix[0]", <shadow_matrix_light_1>);
shaderProgram->setUniform("ShadowMap[0]", 1); (GL_TEXTURE1)
shaderProgram->setUniform("ShadowMatrix[1]", <shadow_matrix_light_2>);
shaderProgram->setUniform("ShadowMap[1]", 2); (GL_TEXTURE2)

The vertex shader is the following (available for just 2 lights):

#version 400

#define MAX_SHADOW_MATRIX 10
#define MAX_SHADOW_COORDS 10

layout (location = 0) in vec4 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
layout (location = 2) in vec2 VertexTexture;

uniform mat3 NormalMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 ShadowMatrix[MAX_SHADOW_MATRIX];
uniform mat4 MVP;

uniform int lightCount;

out vec3 Position;
out vec3 Normal;
out vec2 TexCoords;
out vec4 ShadowCoords[MAX_SHADOW_COORDS];

void main(void)
{
    TexCoords = VertexTexture;
    Normal = normalize(NormalMatrix * VertexNormal);
    Position = vec3(ModelViewMatrix * VertexPosition);
    for (int idx = 0; idx < lightCount; idx++)
        ShadowCoords[idx] = ShadowMatrix[idx] * VertexPosition;
    gl_Position = MVP * VertexPosition;
}

And a piece of code of the fragment shader :

[...]

vec3 evalBasicFragmentShadow(vec3 LightIntensity, int idx)
{
    vec3 Ambient = LightInfos[idx].La * MaterialInfos.Ka;

    if (ShadowCoords[idx].w > 0.0f)
    {
        vec4 tmp_shadow_coords = ShadowCoords[idx];

        tmp_shadow_coords.z -= SHADOW_OFFSET;

        float shadow = textureProj(ShadowMap[idx], tmp_shadow_coords);

        LightIntensity = LightIntensity * shadow + Ambient;
    }
    else
    {
        LightIntensity = LightIntensity + MaterialInfos.Ka;
    }
    return (LightIntensity);
}

vec3 getLightIntensity(vec3 TexColor)
{
    vec3 LightIntensity = vec3(0.0f);

    for (int idx = 0; idx < lightCount; idx++)
    {
        vec3 tnorm = (gl_FrontFacing ? -normalize(Normal) : normalize(Normal));
        vec3 lightDir = vec3(LightInfos[idx].Position) - Position;
        vec3 lightDirNorm = normalize(lightDir);
        float lightAtt = getLightAttenuation(lightDir, LightInfos[idx]);

        LightIntensity += Point_ADS_Shading(lightAtt, -tnorm, lightDirNorm, TexColor, idx);
        LightIntensity = evalBasicFragmentShadow(LightIntensity, idx);
    }
    return (LightIntensity);
}

[...]

It's look like a texture unit problem because separatly the two shadows have been rendered perfectly and I use glActiveTexture correctly (I think so). Plus, I noticed that if I change the loading order of the lights, the bad shadow is caused by 'the other light' (it's the contrary). So it seems to comes from the texture unit 2, but I don't understand why. Does anyone can help me, please ? Thanks a lot in advance for your help.

4

1 回答 1

13

我解决了我的问题。实际上,我只是填充了第一个深度纹理(用于第一个加载的光)。所以对于第二盏灯,阴影贴图没有被填充,这就是上面第三张图片中黑色区域的原因。

这是最终结果:

在此处输入图像描述

在此处输入图像描述

我希望这篇文章对某人有用。感谢您的关注。

于 2013-12-24T13:57:12.247 回答