title: How to efficiently copy depth buffer to texture on OpenGL ES
body: <p>I'm trying to get some shadowing effects to work in OpenGL ES 2.0 on iOS by porting <a href="http://www.codesampler.com/usersrc/usersrc_8.htm" rel="nofollow noreferrer">some code</a> from standard GL. Part of the sample involves copying the depth buffer to a texture:</p>
  
  <pre><code>glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0);
  </code></pre>
  
  <p>However, it appears the glCopyTexImage2D is not supported on ES. Reading a <a href="https://stackoverflow.com/questions/2596682/opengl-es-2-0-read-depth-buffer">related thread</a>, it seems I can use the frame buffer and fragment shaders to extract the depth data. So I'm trying to write the depth component to the color buffer, then copying it:</p>
  
  <pre><code>// clear everything
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
  
  // turn on depth rendering
  glUseProgram(m_BaseShader.uiId);
  
  // this is a switch to cause the fragment shader to just dump out the depth component
  glUniform1i(uiBaseShaderRenderDepth, true);
  
  // and for this, the color buffer needs to be on
  glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
  
  // and clear it to 1.0, like how the depth buffer starts
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
  
  // draw the scene
  DrawScene();
  
  // bind our texture 
  glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, width, height, 0);
  </code></pre>
  
  <p>Here is the fragment shader:</p>
  
  <pre><code>uniform sampler2D sTexture;
  uniform bool bRenderDepth;
  
  varying lowp    float LightIntensity;
  varying mediump vec2  TexCoord;
  
  void main()
  {    
      if(bRenderDepth) {
          gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0);
      } else {
          gl_FragColor = vec4(texture2D(sTexture, TexCoord).rgb * LightIntensity, 1.0);
      }
  }
  </code></pre>
  
  <p>I have experimented with not having the 'bRenderDepth' branch, and it doesn't speed it up significantly.</p>
  
  <p>Right now pretty much just doing this step its at 14fps, which obviously is not acceptable. If I pull out the copy its way above 30fps. I'm getting two suggestions from the Xcode OpenGLES analyzer on the copy command:</p>
  
  <ol>
  <li><p>file://localhost/Users/xxxx/Documents/Development/xxxx.mm: error:
  Validation Error: glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0,
  960, 640, 0) : Height&lt;640> is not a power of two</p></li>
  <li><p>file://localhost/Users/xxxx/Documents/Development/xxxx.mm: warning:
  GPU Wait on Texture: Your app updated a texture that is currently
  used for rendering. This caused the CPU to wait for the GPU to
  finish rendering.</p></li>
  </ol>
  
  <p>I'll work to resolve the two above issues (perhaps they are the crux if of it). In the meantime can anyone suggest a more efficient way to pull that depth data into a texture?</p>
  
  <p>Thanks in advance!</p>