Я борюсь с функцией OpenGL glBlitFramebuffer. В документе говорится, что он поддерживает блиттинг как буфера цвета, так и буфера глубины. Однако на практике это не так. Я на MacBook AIR 13 дюймов, с Intel HD Graphics 5000 1536 МБ.
Мне нужно сделать мультисэмплинг из http://ake.in.th/2013/04/02/offscreening-and-multisampling-with-opengl/
Мой уровень мультисэмплинга 4 (AA_LEVEL = 4), моя версия OpenGL: 3.2 профиля ядра. Вот что я делаю:
Создайте мультисэмпловый буфер кадра AA.
glGenFramebuffers( 1, &_offscreenBufferHandle );
glBindFramebuffer( GL_FRAMEBUFFER, _offscreenBufferHandle );
glGenRenderbuffers(1, &_depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, AA_LEVEL, GL_DEPTH_COMPONENT16, srcWidth_, srcHeight_);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenRenderbuffers(1, &_aaColorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _aaColorbuffer);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, AA_LEVEL, GL_RGBA, srcWidth_, srcHeight_);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Создать целевой буфер кадров
glGenFramebuffers( 1, &_outputBufferHandle );
glBindFramebuffer( GL_FRAMEBUFFER, _outputBufferHandle );
glGenRenderbuffers(1, &_outputColorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _outputColorbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, srcWidth_, srcHeight_);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glGenRenderbuffers(1, &_outputDepthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _outputDepthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, srcWidth_, srcHeight_);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Нарисуйте материал с буфером цвета и глубины
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, _offscreenBufferHandle );
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
//next
DrawStuff();
Поместите мультисэмпловый буфер кадра AA в буфер целевого кадра.
glBindFramebuffer( GL_READ_FRAMEBUFFER, _offscreenBufferHandle );
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, _outputBufferHandle );
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _outputColorbuffer);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _outputDepthbuffer);
if( glCheckFramebufferStatus(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE &&
glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE ) {
//do blitting here
glBlitFramebuffer(0, 0, srcWidth_, srcHeight_, 0, 0, srcWidth_, srcHeight_, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
Считайте пиксели из буфера целевого кадра и выполните некоторую постобработку
//then blit it to pixels buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, _outputBufferHandle);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _outputColorbuffer);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _outputDepthbuffer);
readParam("temp");
GLenum framebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if( framebufferStatus == GL_FRAMEBUFFER_COMPLETE ) {
glReadBuffer(GL_COLOR_ATTACHMENT0);
//getGLErr("GL_COLOR_ATTACHMENT0");
glReadPixels(0, 0, srcWidth_, srcHeight_, GL_BGR, GL_UNSIGNED_BYTE, pixels);
}
Однако в результате ТОЛЬКО удаляется цветовой буфер, без буфера глубины.
Если я отключу мультисэмплинг, изменив значение AA_LEVEL = 0 и заменив этап удаления 4, замените шаг 5 следующим кодом для чтения непосредственно из _offscreenBufferHandle, результат будет выглядеть правильно.
glBindFramebuffer(GL_READ_FRAMEBUFFER, _offscreenBufferHandle);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _aaColorbuffer);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
GLenum framebufferStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
if( framebufferStatus == GL_FRAMEBUFFER_COMPLETE ) {
glReadPixels(0, 0, srcWidth_, srcHeight_, GL_BGR, GL_UNSIGNED_BYTE, pixels);
}
Многие сообщения указывают на подобную проблему, я запутался, является ли это проблема с графической картой, или то, что я делал, неправильно.
https://gamedev.stackexchange.com/questions/68290/fbo-blit-depth-buffer-to-screen
https://www.opengl.org/discussion_boards/showthread.php/176317-Framebuffer-not-bliting-depth-buffer
В этих статьях это означает, что мне нужно нарисовать текстурированный квад, чем сделать блиц из буфера чтения в буфер рисования. Это слишком много проблем.
Задача ещё не решена.