OpenGL - невозможно записать в буфер кадра (или прочитать его правильно)

Итак, я пытался заставить работать отображение теней, но безуспешно, и теперь я пытаюсь просто записать что-нибудь в буфер кадра, а затем отрендерить его в четырехугольник как текстуру. Я смотрел на этот небольшой фрагмент кода в течение 10 часов, поэтому я подумал, что, возможно, пришло время обратиться за помощью. Дайте мне знать, если вам нужна дополнительная информация или если что-то неясно.

Я начал с этого учебника. Выполнив его два раза и скопировав в третий раз, я сдался и начал искать информацию в другом месте. Мой текущий код немного запутан, но я попытался извлечь то, что имеет решающее значение.

Вот как я настроил свой FBO с помощью TEXTURE2D (_shadowMap и _shadowMapFBO — частные переменные в классе, выступающем в роли основной программы):

glGenTextures(1, &_shadowMap);
glBindTexture(GL_TEXTURE_2D, _shadowMap);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

glGenFramebuffers(1, &_shadowMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowMap, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{
    std::cout << "Frame buffer failed" << std::endl;
    system("pause");
    exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);

Затем я делаю первый проход рендеринга в основном цикле:

glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
_shadowShader.bind();
glBindVertexArray(_cubeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesCube, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(_planeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesPlane, GL_UNSIGNED_SHORT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);

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

Вершина

#version 450

in layout(location=0) vec3 position;

uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4(position, 1.0f);
}

Фрагмент

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

Затем я заканчиваю, пытаясь отобразить текстуру на четырехугольнике:

glViewport(0, 0, _screenWidth, _screenHeight);
glClearColor(0.7f, 0.5f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_testShader.bind();
glBindTexture(GL_TEXTURE_2D, _shadowMap);
glBindVertexArray(_quadVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

Вот фрагментный шейдер для четырехугольника:

#version 450

in vec2 textureCoordinates;

uniform sampler2D _shadowMap;

out vec4 color;

void main()
{
    float depth = texture2D(_shadowMap, textureCoordinates).r;
    color = texture2D(_shadowMap, textureCoordinates);
}

Но, к моему постоянному разочарованию, четырехугольник выглядит белым, хотя я вывожу 0.0f (черный) из фрагментного шейдера... Я знаю, что четырехугольник может отображать текстуру, так как я смог отобразить обычную текстуру, отображающую файл . jpg на него. Итак, вот где я сейчас; любые идеи, указатели, мысли, мотивационные слова и т. д.?

РЕДАКТИРОВАТЬ I: Итак, спустя некоторое время я, по крайней мере, понял, что текстура загружается правильно и что я могу ее читать. Я сделал это, фактически загрузив изображение во время инициализации, а затем не записывая его. Квадрат правильно отображает текстуру. Значит, должно быть что-то не так с тем, как я пишу на него.

РЕДАКТИРОВАТЬ II: Итак, я заработал; Я сел с ассистентом и скопировал код (да, я знаю... лучше не бывает), и теперь он работает. Спасибо Барт :)


person MulattoKid    schedule 26.11.2016    source источник


Ответы (1)


Ваш шейдер фрагмента теневого прохода просто неверен:

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

Это просто объявляет вывод одного канала color, который будет записан во вложение цвета (которого у вас нет). Так как вы хотите писать в глубине вашего FBO, вы должны использовать встроенный gl_FragDepth выходная переменная. Если вы этого не сделаете, GL запишет линейно интерполированное значение глубины оконного пространства в буфер глубины.

Обратите внимание, что обычно вы очищаете буфер глубины до 1,0, и при использовании типичной перспективной проекции ваши объекты будут казаться очень близкими к 1,0, скажем, 0,99 с чем-то, как значение глубины, поэтому очень вероятно, что преобразование результата в просто 8-битные оттенки серого будут выглядеть полностью белыми.

person derhass    schedule 27.11.2016
comment
Спасибо за ответ; так что я на самом деле получил это работает, как раз собирался написать это. Я попробовал то, что вы предлагаете, сделав gl_fragDepth = 0.2f, но это тоже не сработало (это было до того, как я опубликовал это здесь). Я получил некоторую помощь от одного из моих ассистентов, и по какой-то причине, когда он сел со мной и скопировал код из учебника, он сработал. Спасибо, в любом случае :) - person MulattoKid; 29.11.2016