Эффективный способ чтения значений глубины из буфера глубины - PullRequest
6 голосов
/ 23 августа 2011

Для моего алгоритма мне нужно иметь доступ к буферу глубины.У меня нет проблем, когда я делаю это с использованием glReadPixels, но чтение окна 800x600 очень медленно (от 300 кадров в секунду до 20 кадров в секунду)

Я много читаю об этом и думаю, что дамп буфера глубины вТекстура будет быстрее.Я знаю, как создать текстуру, но как мне получить глубину?

Создание FBO и создание текстуры оттуда может быть еще быстрее, на данный момент я использую FBO (но все еще в комбинациис glReadPixels).

Так что это самый быстрый способ сделать это?

(я, вероятно, не могу использовать GLSL, потому что я ничего не знаю об этом, и у меня не так много времени, чтобы учиться, сроки!)

edit: БудетПБО работаешь?Как описано здесь: http://www.songho.ca/opengl/gl_pbo.html это может идти намного быстрее, но я не могу все время менять буферы, как в примере.

Edit2: Как мне поступить с помещением данных глубины в PBO?На данный момент я делаю:

glGenBuffersARB(1, &pboId);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat),0,     GL_STREAM_READ_ARB);

и прямо перед чтением пикселей я снова вызываю glBindbuffer.В результате я вообще ничего не читаю.Если я отключаю PBO, все это работает.

Окончательное редактирование: думаю, я решил это, мне пришлось использовать:

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));

GLuint *pixels = (GLuint*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);

Это дало мне увеличение на 20 FPS.Это не так уж много, но это что-то.

Итак, я использовал 2 PBO, но все еще сталкиваюсь с проблемой: мой код выполняется только один раз.

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);  
std::cout << "Reading pixels" << std::endl;
glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));
std::cout << "Getting pixels" << std::endl;
//  glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat), 0, GL_STREAM_DRAW_ARB);
GLfloat *pixels = (GLfloat*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
int count = 0;
for(int i = 0; i != 800*600; ++i){
    std::cout << pixels[i] << std::endl;
}

Последняя строка выполняется один раз, но только один раз, после этого он продолжает вызывать метод (что нормально), но останавливается на вызове пикселей.


Я, видимо, забыл загрузить glUnMapBuffers, что-то вроде решило это, хотя моя частота кадров снова стала медленнее ..


Я решил попробовать FBO, но наткнулся напроблема: Инициализация FBO:

glGenFramebuffersEXT(1, framebuffers);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);
std::cout << "framebuffer generated, id: " << framebuffers[0] << std::endl;
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

glGenRenderbuffersEXT(1,renderbuffers);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffers[0]);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 800, 600);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffers[0]);
bool status = checkFramebufferStatus();
    if(!status)
        std::cout << "Could not initialise FBO" << std::endl;
    else
        std::cout << "FBO ready!" << std::endl;

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

Мой цикл рисования:

GLenum errCode;const GLubyte * errString;

if ((errCode = glGetError()) != GL_NO_ERROR) {
    errString = gluErrorString(errCode);
   fprintf (stderr, "OpenGL Error: %s\n", errString);
}

++frameCount;
// -----------  First pass to fill the depth buffer  -------------------
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);

std::cout << "FBO bound" << std::endl;
//Enable depth testing
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDepthMask( GL_TRUE );
//Disable stencil test, we don't need that for this pass
glClearStencil(0);
glEnable(GL_STENCIL_TEST);

//Disable drawing to the color buffer
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

//We clear all buffers and reset the modelview matrix
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();

//We set our viewpoint
gluLookAt(eyePoint[0],eyePoint[1], eyePoint[2], 0.0,0.0,0.0,0.0,1.0,0.0);
//std::cout << angle << std::endl;
std::cout << "Writing to FBO depth" << std::endl;
//Draw the VBO's, this does not draw anything to the screen, we are just filling the depth buffer
glDrawElements(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

После этого я вызываю функцию, которая вызывает glReadPixels () Функция даже не вызывается.Цикл перезапускается при вызове функции.


Видимо, я решил и это: мне пришлось использовать

glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT, pixels);

с GL_UNSIGNED_SHORT вместо GL_FLOAT (или любым другим форматом в этом отношении)

Ответы [ 2 ]

4 голосов
/ 23 августа 2011

Самый быстрый способ сделать это - использовать асинхронные пиксельные буферные объекты, здесь есть хорошее объяснение:

http://www.songho.ca/opengl/gl_pbo.html

2 голосов
/ 25 августа 2011

Я рендерился бы в FBO и считывал его буфер глубины после рендеринга кадра.PBOs устарели технологии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...