Multi lights shadow mapping работает неправильно с помощью GLSL
я реализовал основной алгоритм теневого отображения, но он работает правильно только с одним светом.
Я хочу сделать сцену с двумя следующими точечными огнями:
- Light_1-положение: vec3(-8.0 f, 5.0 f, 8.0 f), направление : vec3 (1.3 f, -1.0 f, -1.0 f)
- Light_2-положение: vec3(8.0 f, 5.0 f, 8.0 f), направление : vec3 (1.3 f, -1.0 f, -1.0 f)
если я представляю отдельно два света, у меня есть следующее результаты:
рендеринг с Light_1 :
рендеринг с Light_2 :
но эти два света вместе это выглядит так :
как вы можете видеть, первая тень, кажется, отображается правильно, но она находится ниже тени 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)
вершинный шейдер следующий (доступен только для 2 огней):
#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, но я не понимаю, почему. Кто-нибудь может мне помочь ? Большое спасибо заранее за вашу помощь.
1 ответов
Я решил свою проблему. На самом деле, я просто заполнил первую текстуру глубины (для первого загруженного света). Поэтому для второго света теневая карта не была заполнена, и это объясняет черную область на третьем изображении выше.
вот окончательный результат :
Я надеюсь, что этот пост будет полезным для кого-то. Спасибо за внимание.