4

I'm trying to get some shadowing effects to work in OpenGL ES 2.0 on iOS by porting some code from standard GL. Part of the sample involves copying the depth buffer to a texture:

glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 0, 0, 800, 600, 0);

However, it appears the glCopyTexImage2D is not supported on ES. Reading a related thread, 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:

// 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);

Here is the fragment shader:

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);
    }
}

I have experimented with not having the 'bRenderDepth' branch, and it doesn't speed it up significantly.

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:

  1. file://localhost/Users/xxxx/Documents/Development/xxxx.mm: error: Validation Error: glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 960, 640, 0) : Height<640> is not a power of two

  2. 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.

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?

Thanks in advance!

Community
  • 1
  • 1
mobob
  • 849
  • 10
  • 17
  • I have not tried this yet, but couldn't you write the depth information to the color buffer of a render texture using your fragment shader, then use that as the input to another shader for post processing? OpenGL should then do the syncing on the GPU only and you wouldn't stall the pipeline for performing a CPU-based readback/copy. Also see related discussion [here](http://stackoverflow.com/questions/2596682/opengl-es-2-0-read-depth-buffer) – starbugs Oct 30 '12 at 21:19

1 Answers1

7

iOS devices generally support OES_depth_texture, so on devices where the extension is present, you can set up a framebuffer object with a depth texture as its only attachment:

GLuint g_uiDepthBuffer;
glGenTextures(1, &g_uiDepthBuffer);
glBindTexture(GL_TEXTURE_2D, g_uiDepthBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
// glTexParameteri calls omitted for brevity

GLuint g_uiDepthFramebuffer;
glGenFramebuffers(1, &g_uiDepthFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, g_uiDepthFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, g_uiDepthBuffer, 0);

Your texture then receives all the values being written to the depth buffer when you draw your scene (you can use a trivial fragment shader for this), and you can texture from it directly without needing to call glCopyTexImage2D.

Pivot
  • 3,456
  • 25
  • 20
  • You are 100% correct. I was basing my understanding of what was supported based on the open gl 2.0 ES spec, which excludes any mentions of Extensions. All iOS ES 2.0 devices support OES_depth_texture, so that is indeed the solution. Thanks! – mobob Nov 03 '12 at 19:08
  • So it's okay to have a framebuffer with depth only attachement? – Viktor Sehr Nov 15 '15 at 17:48