Рендеринг сцены OpenGL в черный цвет с отображением теней

Я пытаюсь реализовать отображение теней в моем движке OpenGL, используя этот учебник: http://www.fabiensanglard.net/shadowmapping/index.php

У меня нет проблем при создании карты теней (я думаю). Но с его помощью сцена полностью затенена.

Способ рендеринга моей сцены выглядит следующим образом:

  • Установите глубину FBO

    GLuint sdepthtex;
    GLuint sframebuffer ;
    
    glGenTextures(1, &sdepthtex);
    glBindTexture(GL_TEXTURE_2D, sdepthtex);
    
    glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
    
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, sdepthtex, 0);
    
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
    
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
    displayMessage("Error loading the Depth Framebuffer");
    return;
    }
    

  • Создайте матрицу ModelViewProjection с точки зрения источника света и сохраните ее в переменной shadowMatrix.

Функция, которую я использую:

Matrix getMVPmatrix(vector3 position,vector3 lookat )
{

glPushMatrix();

double projection[16];
double modelView[16];
SDL_Surface*screen = SDL_GetVideoSurface();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FOVY,screen->w/screen->h,NEAR,FAR);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glLoadIdentity();
gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);

glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
glGetDoublev(GL_PROJECTION_MATRIX, projection);

Matrix m1(projection);
Matrix m2(modelView);

glPopMatrix();

return m1*m2;

}

  • Визуализируйте сцену в кадровом буфере глубины. Шейдеры:

Вершинный шейдер:

uniform mat4 shadowMatrix;

void main()
{

gl_Position = shadowMatrix*gl_Vertex;

}

Фрагмент шейдера:

void main(void)
{

gl_FragDepth = gl_FragCoord.z;

}

Для моей сцены из 3 блоков линеаризованная глубина выглядит следующим образом:

http://www.2shared.com/photo/IExy9aUo/Depth.html

Так что я думаю, что shadowMatrix и глубина рендеринга являются правильными.

  • Последний проход как раз прорисовывает сцену с картой теней

Вершинный шейдер:

varying vec4 ShadowCoord;
uniform mat4 shadowMatrix;

mat4 biasMatrix = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);

void main (void)
{
gl_TexCoord[0] =  gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
gl_Position = ftransform();
ShadowCoord = biasMatrix*shadowMatrix *vec4(gl_Vertex.xyz,1.0);
}

Фрагмент шейдера:

uniform sampler2D tex;
uniform sampler2D shadowtex;//the non linearized depth texture we made in the 3rd step.
varying vec4 ShadowCoord;

float getShadowFactor(void)
{
vec4 shadowCoordinateWdivide = ShadowCoord / ShadowCoord.w ;

shadowCoordinateWdivide.z += 0.0005;

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

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

return shadow ;

}

void main (void)
{

gl_FragColor =texture2D(tex, gl_TexCoord[0].st);

gl_FragColor.rgb *= getShadowFactor() ;//add shadows Here

}

Результат ? вся моя сцена затенена!

1

Решение

Похоже, в вашем коде есть несоответствие между настройкой текстуры и шейдером. В коде настройки текстуры у вас есть это:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);

когда GL_TEXTURE_COMPARE_FUNC не является GL_NONEВам необходимо использовать сэмплер теневых текстур в вашем коде шейдера. Но в вашем фрагментном шейдере вы используете обычный сэмплер для этой текстуры:

uniform sampler2D shadowtex;

Это должно быть изменено на это, чтобы быть совместимым с настройками текстуры:

uniform sampler2DShadow shadowtex;

Чтобы соответствовать типу, shadow2D() затем используется вместо texture2D() образец текстуры.

Другой вариант заключается в том, что вы продолжаете GL_TEXTURE_COMPARE_FUNC по умолчанию значение GL_NONE, Это тогда согласуется с использованием sampler2D для отбора проб.

1

Другие решения


По вопросам рекламы [email protected]