2013-12-09 2 views
1

У меня есть сцена, состоящая из 2-х сеток (плоскость, куб), свет и камера. Я хочу отображать тени на своей сцене с использованием технологии теневого отображения с помощью шейдеров GLSL и OpenGL.Теневое отображение работает неправильно с использованием GLSL и OpenGL

Вот результат у меня есть (для простоты, мой куб и мой самолет оба в синем цвете и цвете):

enter image description here

Вот инициализация FBO и глубина текстуры:

GLfloat border[] = {1.0f, 1.0f, 1.0f, 1.0f}; 

    glGenTextures(1, &this->m_TextId); 
    glBindTexture(GL_TEXTURE_2D, this->m_TextId); 

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 
     this->m_Width, this->m_Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); 

    glBindTexture(GL_TEXTURE_2D, 0); 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, this->m_TextId, 0); 

    glDrawBuffer(GL_NONE); 
    glReadBuffer(GL_NONE); 

    GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    if(result == GL_FRAMEBUFFER_COMPLETE) { 
     printf("Framebuffer is complete.\n"); 
    } else { 
     printf("Framebuffer is not complete.\n"); 
    } 

Вот содержание моего вершинного шейдера:

#version 400 
layout (location = 0) in vec3 VertexPosition; 
layout (location = 1) in vec3 VertexNormal; 
layout (location = 2) in vec2 VertexTexture; 

uniform mat4 MVP; 
uniform mat4 ShadowMatrix; 

out vec4 ShadowCoords; 

void main(void) 
{ 
    ShadowCoords = ShadowMatrix * vec4(VertexPosition, 1.0f); 
    gl_Position = MVP * vec4(VertexPosition, 1.0f); 
} 

И один из моего пиксельного шейдера:

#version 400 

in vec3 Position; 
in vec3 Normal; 
in vec2 TexCoords; 
in vec4 ShadowCoords; 

layout (location = 0) out vec4 FragColor; 

uniform sampler2DShadow ShadowMap; 

void main(void) 
{ 
    vec4 ModelColor = vec4(0.0f, 0.0f, 1.0f, 1.0f); 

    float shadow = textureProj(ShadowMap, ShadowCoords); 

    FragColor = ModelColor * shadow; 
} 

Как вы можете видеть, что есть некоторые артефакты на моделях, и я не знаю, как вывести их. Но тень кажется правильной, поэтому переменные, входящие в мои шейдеры, тоже должны быть правильными (я так думаю).

Я попробовал другую технику в пиксельный шейдер, как следующий:

#version 400 

in vec3 Position; 
in vec3 Normal; 
in vec2 TexCoords; 
in vec4 ShadowCoords; 

layout (location = 0) out vec4 FragColor; 

uniform sampler2D ShadowMap; 

void main(void) 
{ 
    vec4 ModelColor = vec4(0.0f, 0.0f, 1.0f, 1.0f); 

    vec4 shadowCoordinateWdivide = ShadowCoords/ShadowCoords.w; 

    shadowCoordinateWdivide.z += 0.0005; 

    float distanceFromLight = texture2D(ShadowMap,shadowCoordinateWdivide.st).z; 

    float shadow = 1.0; 
    if (ShadowCoords.w > 0.0) 
     shadow = (distanceFromLight < shadowCoordinateWdivide.z) ? 0.5 : 1.0 ; 

    FragColor = shadow * ModelColor; 
} 

Вы можете заметить, что я не использую sampler2DShadow но теперь sampler2D. Но, как вы можете увидеть там отображается ни тени:

enter image description here

Кто-нибудь может мне помочь?

ответ

2

Ваше первое изображение может быть объяснено проблемами с плавающей запятой. Когда вы трансформируете свою вершину с помощью теневой матрицы, вы получите точку, расстояние от которой почти равно глубине буфера глубины света (поскольку точка лежит на геометрии). Для некоторых из этих точек преобразование даст небольшую глубину света перед геометрией, а для других глубина будет немного за гранью геометрии. Следовательно, половина из них заканчивается окклюдированием по какой-то странной схеме.

Что вы хотите сделать, это нарушить координаты Z координаты маленькой точки в сторону света, чтобы избежать этой проблемы.

+0

Спасибо, что все правильно работают. До свидания. – user1364743

Смежные вопросы