Pergunta

I'm working on an implementation of the "Depth on Field" in OpenGL (3.X) with GLSL. It works pretty good, central depth is taken up by shaders (texture (tex1, vec2 (0.5))) to autofocus. But using such an implementation focus happens immediately. He should like the eye - gradually adapt. For this I need the depth in the middle on the side of the CPU memory. I know how to use the PBO, use it to read the pixel / pixel color works pretty fast (runs asynchronously), but changing the GL_RGB to GL_DEPTH_COMPONENT performance drops drastically. Do you know any way to read that the central depth comparatively quickly what color?

    glReadPixels(a/2, b/2, 1, 1, GL_RGB , GL_BYTE, 0); // WORKS FINE - 30 ns
    glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_BYTE, 0); // WORKS SLOOOW - around 3500 microseconds
    glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0); // WORKS SLOOOW- around 3500 microseconds

@EDIT: Created FBO texture:

glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT32F , sett.framebuffer_width,  sett.framebuffer_height, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);

Downloading Depth:

index = (index + 1) % 2;// for ping-pong PBO
nextIndex = (index + 1) % 2;// for ping-pong PBO
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);
glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT , GL_FLOAT, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);

Copying depth to ram:

GLfloat tabc[10];
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pboIds[nextIndex]);
GLfloat* srccccc = (GLfloat*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
tabc[0]=*srccccc;
std::cout<<"Depth center: "<<tabc[0]<<std::endl;//only to check is that correct
glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);     

It's working now, much faster (357 microseconds from 3500 microseconds). Is it good right now? All formats?

Foi útil?

Solução

glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_BYTE, 0); // WORKS SLOOOW - around 3500 ns
glReadPixels(a/2, b/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, 0); // WORKS SLOOOW- around 3500 ns

Of course they're slow. Generally speaking, the depth buffer will be neither a 8-bit byte nor a 32-bit floating-point value. The reason your readback of the colors worked quickly was because your pixel transfer format and type matched your framebuffer. And since you're very wisely using PBOs in your readback, having to do CPU-based conversion on the value will kill your performance.

So you need to do the same thing here: match the pixel transfer parameters with the framebuffer images.

If you're reading from an FBO, then you should know the exact bitdepth of your images (you are using sized internal formats, right?). So simply match that:

GL_DEPTH_COMPONENT16  -> GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT
GL_DEPTH_COMPONENT32  -> GL_DEPTH_COMPONENT, GL_UNSIGNED_INT
GL_DEPTH_COMPONENT32F -> GL_DEPTH_COMPONENT, GL_FLOAT

There's one more pure depth buffer format: GL_DEPTH_COMPONENT24. You can probably just use GL_UNSIGNED_INT with this, but odds are good that OpenGL will have to expand the data to 32-bits when writing it.

That's one reason you should use GL_DEPTH24_STENCIL8 instead. For that one, you can do this:

GL_DEPTH24_STENCIL8 -> GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8

You'll have to right-shift each 32-bit value by 8 bits and mask out the top 8 bits when you want the depth value. But it should work.

If you're reading from the default framebuffer, that's a bit trickier. Odds are good that, when you set up your rendering context, you told OpenGL what bitdepths you wanted in your framebuffer. But you may not have gotten them, so you need to ask.

To do this, you need to employ glGetFramebufferAttachmentParameter. With that, you can query GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE​ from the GL_DEPTH attachment, and GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE​ from the GL_STENCIL attachment. It's important that you test both of these; if you have both depth and stencil bits, you need to use a depth/stencil read.

Once you have the bitdepths, just pretend they were one of the above internal formats and proceed as normal.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top