title: Efficient way of reading depth values from depth buffer
body: <p>For an algorithm of mine I need to be able to access the depth buffer. I have no problem at all doing this using glReadPixels, but reading an 800x600 window is extremely slow (From 300 fps to 20 fps)</p>
  
  <p>I'm reading a lot about this and I think dumping the depth buffer to a texture would be faster. I know how to create a texture, but how do I get the depth out?</p>
  
  <p>Creating an FBO and creating the texture from there might be even faster, at the moment I am using an FBO (but still in combination with glReadPixels).</p>
  
  <p>So what is the fastest way to do this? </p>
  
  <p>(I'm probably not able to use GLSL because I don't know anything about it and I don't have much time left to learn, deadlines!)</p>
  
  <p>edit: 
  Would a PBO work? As described here: <a href="http://www.songho.ca/opengl/gl_pbo.html" rel="nofollow">http://www.songho.ca/opengl/gl_pbo.html</a> it can go a lot faster but I can not change buffers all the time as in the example.</p>
  
  <p>Edit2:
  How would I go about putting the depth data in the PBO? At the moment I do:</p>
  
  <pre><code>glGenBuffersARB(1, &amp;pboId);
  glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
  glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, 800*600*sizeof(GLfloat),0,     GL_STREAM_READ_ARB);
  </code></pre>
  
  <p>and right before my readpixels i call glBindbuffer again. The effect is that I read nothing at all. If I disable the PBO's it all works.</p>
  
  <p>Final edit: 
  I guess I solved it, I had to use:</p>
  
  <pre><code>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);
  </code></pre>
  
  <h2>This gave me a 20 FPS increase. It's not that much but it's something.</h2>
  
  <p>So, I used 2 PBO's but I'm still encountering a problem: My code only gets executed once.</p>
  
  <pre><code>glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[index]);  
  std::cout &lt;&lt; "Reading pixels" &lt;&lt; std::endl;
  glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_FLOAT, BUFFER_OFFSET(0));
  std::cout &lt;&lt; "Getting pixels" &lt;&lt; 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 &lt;&lt; pixels[i] &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>The last line executes once, but only once, after that it keeps on calling the method (which is normal) but stops at the call to pixels. </p>
  
  <hr>
  
  <p>I apparently forgot to load glUnMapBuffers, that kinda solved it, though my framerate is slower again..</p>
  
  <hr>
  
  <p>I decided giving FBO's a go, but I stumbled across a problem:
  Initialising FBO:</p>
  
  <pre><code>glGenFramebuffersEXT(1, framebuffers);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffers[0]);
  std::cout &lt;&lt; "framebuffer generated, id: " &lt;&lt; framebuffers[0] &lt;&lt; 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 &lt;&lt; "Could not initialise FBO" &lt;&lt; std::endl;
      else
          std::cout &lt;&lt; "FBO ready!" &lt;&lt; std::endl;
  
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  </code></pre>
  
  <p>My drawing loop:</p>
  
  <p>GLenum errCode;
      const GLubyte *errString;</p>
  
  <pre><code>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 &lt;&lt; "FBO bound" &lt;&lt; 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 &lt;&lt; angle &lt;&lt; std::endl;
  std::cout &lt;&lt; "Writing to FBO depth" &lt;&lt; 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));
  </code></pre>
  
  <p>After this I call a function that calls glReadPixels()
  The function does not even get called. The loop restarts at the function call.</p>
  
  <hr>
  
  <p>Apparently I solved this as well: I had to use </p>
  
  <pre><code>glReadPixels( 0, 0,Engine::fWidth, Engine::fHeight, GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT, pixels);
  </code></pre>
  
  <p>With GL_UNSIGNED_SHORT instead of GL_FLOAT (or any other format for that matter)</p>