Отложенные шейдерные текстуры от FBO отображаются черными

Я пытаюсь использовать отложенное затенение для реализации SSAO, и у меня возникают проблемы с доступом к моим текстурам в шейдере с отложенным фрагментом. Код написан на C ++ / Qt5 и использует Coin3D для генерации остальной части пользовательского интерфейса (но здесь это не должно иметь большого значения).

Фрагмент шейдера отложенного прохода:

#version 150 compatibility

uniform sampler2D color;
uniform sampler2D position;
uniform sampler2D normal;

uniform vec3 dim;
uniform vec3 camPos;
uniform vec3 camDir;

void main()
{
// screen position
vec2 t = gl_TexCoord[0].st;

// the color
vec4 c = texture2D(color, t);

gl_FragColor = c + vec4(1.0, t.x, t.y, 1.0);
}

Код для запуска отложенного прохода

_geometryBuffer.Unbind();

// push state
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

glPushAttrib(GL_DEPTH_BUFFER_BIT |
GL_COLOR_BUFFER_BIT |
GL_LIGHTING_BIT |
GL_SCISSOR_BIT |
GL_POLYGON_BIT |
GL_CURRENT_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_CULL_FACE);
}

// bind shader
// /!\ IMPORTANT to do before specifying locations
_deferredShader->bind();

_CheckGLErrors("deferred");

// specify positions
_deferredShader->setUniformValue("camPos", ...);
_deferredShader->setUniformValue("camDir", ...);
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_NORMAL, 2);
_deferredShader->setUniformValue("normal", GLint(2));
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_POSITION, 1);
_deferredShader->setUniformValue("position",  GLint(1));
_geometryBuffer.Bind(GBuffer::TEXTURE_TYPE_DIFFUSE, 0);
_deferredShader->setUniformValue("color",  GLint(0));

_CheckGLErrors("bind");

// draw screen quad
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glColor3f(0, 0, 0);
glVertex2f(-1, -1);

glTexCoord2f(1, 0);
glColor3f(0, 0, 0);
glVertex2f( 1, -1);

glTexCoord2f(1, 1);
glColor3f(0, 0, 0);
glVertex2f( 1,  1);

glTexCoord2f(0, 1);
glColor3f(0, 0, 0);
glVertex2f(-1,  1);
glEnd();
}

_deferredShader->release();

// for debug
_geometryBuffer.Unbind(2);
_geometryBuffer.Unbind(1);
_geometryBuffer.Unbind(0);
_geometryBuffer.DeferredPassBegin();
_geometryBuffer.DeferredPassDebug();

// pop state
{
glPopAttrib();

glMatrixMode(GL_PROJECTION);
glPopMatrix();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}

Я знаю, что текстуры были правильно обработаны при создании буфера геометрии, потому что я могу записать их в файлы и получить ожидаемый результат.

Отсроченный проход не работает. Шейдер скомпилирован правильно, и я получаю следующий результат на экране:

Плохой результат

И последняя часть моего кода (DeferredPassBegin / Debug) — нарисовать FBO на экране (как показано на скриншоте) в качестве доказательства правильности GBuffer.

Текущий результат, по-видимому, означает, что текстуры неправильно привязаны к их соответствующей униформе, но я знаю, что содержимое является действительным, так как я выгрузил текстуры в файлы и получил те же результаты, что показаны выше.

Мои функции привязки в GBuffer:

void GBuffer::Unbind()
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}

void GBuffer::Bind(TextureType type, uint32_t idx)
{
glActiveTexture(GL_TEXTURE0 + idx);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textures[static_cast<uint32_t>(type)]);
}

void GBuffer::Unbind(uint32_t idx)
{
glActiveTexture(GL_TEXTURE0 + idx);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}

Наконец, текстуры 512/512, и я создал их в своем GBuffer с помощью:

WindowWidth = WindowHeight = 512;
// Create the FBO
glGenFramebuffers(1, &_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, _fbo);

const uint32_t NUM = static_cast<uint32_t>(NUM_TEXTURES);

// Create the gbuffer textures
glGenTextures(NUM, _textures);
glGenTextures(1, &_depthTexture);

for (unsigned int i = 0 ; i < NUM; i++) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WindowWidth, WindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i + _firstIndex, GL_TEXTURE_2D, _textures[i], 0);
}

// depth
glBindTexture(GL_TEXTURE_2D, _depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);

GLenum buffers[NUM];
for(uint32_t i = 0; i < NUM; ++i){
buffers[i] = GLenum(GL_COLOR_ATTACHMENT0 + i + _firstIndex);
}
glDrawBuffers(NUM, buffers);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
printf("FB error, status: 0x%x\n", status);
return _valid = false;
}

// unbind textures
glBindTexture(GL_TEXTURE_2D, 0);

// restore default FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);

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

Редактировать 1

Как и просили, код для DeferredPassBegin / Debug (в основном приходит от этот урок )

void GBuffer::DeferredPassBegin() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
}

void GBuffer::DeferredPassDebug() {
GLsizei HalfWidth = GLsizei(_texWidth / 2.0f);
GLsizei HalfHeight = GLsizei(_texHeight / 2.0f);

SetReadBuffer(TEXTURE_TYPE_POSITION);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
0, 0, HalfWidth, HalfHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);

SetReadBuffer(TEXTURE_TYPE_DIFFUSE);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
0, HalfHeight, HalfWidth, _texHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);

SetReadBuffer(TEXTURE_TYPE_NORMAL);
glBlitFramebuffer(0, 0, _texWidth, _texHeight,
HalfWidth, HalfHeight, _texWidth, _texHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}

3

Решение

Arghk !!!

Поэтому я ожидал, что параметры текстуры не являются обязательными, но когда я посмотрел какой-то код, я просто попытался указать параметры текстуры. При генерации текстур FBO, я использую сейчас

for (unsigned int i = 0 ; i < NUM; i++) {
glBindTexture(GL_TEXTURE_2D, _textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WindowWidth, WindowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i + _firstIndex, GL_TEXTURE_2D, _textures[i], 0);
}

И с этим изменением я получаю ожидаемый результат (только с c в фрагментном шейдере и аналогичных правильных результатах, если я переключусь на визуализацию нормали / положения).

Заключение: необходимо указать параметры текстуры для отложенного затенения для работы (по крайней мере, с настройкой графики моего приложения / машины).

Правильный кролик

0

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