Многократное отображение теневых изображений работает неправильно, используя GLSL - программирование

Многократное отображение теневых изображений работает неправильно, используя GLSL

Я реализовал основной алгоритм преобразования теней, но он работает правильно только с одним светом.

Я хочу сделать сцену с двумя следующими точечными огнями:

  • Light_1 - позиция: vec3 (-8.0f, 5.0f, 8.0f), направление: vec3 (1.3f, -1.0f, -1.0f)
  • Light_2 - позиция: vec3 (8.0f, 5.0f, 8.0f), направление: vec3 (1.3f, -1.0f, -1.0f)

Если я визуализирую отдельно два индикатора, у меня есть следующие результаты:

Рендеринг с помощью Light_1:

enter image description here

Рендеринг с помощью Light_2:

enter image description here

Но два света вместе выглядят так:

enter image description here

Как вы видите, первая тень, кажется, отображается правильно, но она ниже тени light_2, которая неверна. Чтобы подвести итог ситуации, у меня есть текстура моего ящика, привязанного к текстурному блоку 0. Текстура глубины тени привязана от блока текстуры 1, и если имеется более одной текстуры глубины (так, по крайней мере, две лиги, как в этот пример), привязаны к текстурному блоку 1 + 1 (GL_TEXTURE1 + 1). Вот код, который представляет то, что я сказал:

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);

В нашем случае это соответствует:

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)

Вершинный шейдер следующий (доступно только для двух огней):

#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;
}

И фрагмент кода шейдера фрагмента:

[...]

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);
}

[...]

Это похоже на проблему с блоком текстур, потому что разделительно две тени были визуализированы отлично, и я правильно использую glActiveTexture (я так думаю). Кроме того, я заметил, что если я изменил порядок загрузки огней, плохая тень вызвана "другим светом" (это наоборот). Похоже, что это происходит из текстурного блока 2, но я не понимаю, почему. Кто-нибудь может мне помочь, пожалуйста? Большое спасибо за вашу помощь.

4b9b3361

Ответ 1

Я решил свою проблему. На самом деле, я просто заполнил первую глубину (для первого загруженного света). Итак, для второго света теневая карта не была заполнена, и это то, что объясняет черную область на третьем изображении выше.

Здесь конечный результат:

enter image description here

enter image description here

Я надеюсь, что этот пост будет полезен для кого-то. Спасибо за внимание.