1
\$\begingroup\$

I have 2 different shaders, and when I change the shader (glUseProgram), it seems that the depth information is lost, because everything drawn with the 2nd shader appears completely on top of anything drawn by the first shader.

If I switch the order of shader use/drawing, then it's the same (the last drawn object always appears on top of the first drawn object if there is a shader change between the 2 objects, even if the last drawn object is further away)

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

I'll confirm that the depth buffer is not cleared by OpenGL ES2 when changing shaders.

If it appears to be doing so in your code, that indicates a bug on your side. Check for calls to glClear(GL_DEPTH_BUFFER_BIT) which might be getting triggered indirectly from your shader-changing code (I recommend putting a breakpoint on every call to glClear in a debugger, to see exactly when they're being called)

You should probably also check that you're not calling glDisable(GL_DEPTH_TEST) or modifying glDepthFunc() in a way that would result in the depth buffer appearing to have been cleared, when actually the depth test has been completely disabled (these two different issues can often look identical, in many types of scenes).

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for this answer. It turned out I didn't have a depth buffer attached. \$\endgroup\$
    – bobobobo
    Commented Oct 1, 2012 at 2:48
1
\$\begingroup\$

Ok, I had the depth test enabled but I didn't have a depth buffer. That was surprising!

To add a depth buffer in ES2:

The entire init and resizeFromLayer functions become:

// Create an ES 2.0 context
- (id <ESRenderer>) init
{
  if (self = [super init])
  {
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

    // Create the vertex formats + shaders
    if (!context || ![EAGLContext setCurrentContext:context] || ![self loadShaders])
    {
      return nil;
    }


    // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
    glGenFramebuffers(1, &defaultFramebuffer);
    glGenRenderbuffers(1, &colorRenderbuffer);


    glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

    /////NEW!!////////////////////////
    glGenRenderbuffers(1, &depthRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
  }     
  return self;
}

- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{
  // Allocate color buffer backing based on the current layer size
  glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];

  int backingWidth,backingHeight;

  /////NEW!!////////////////////////
  glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
  glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
  glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, backingWidth, backingHeight);
  glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer); // linked post says need this

  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
  {
    NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    return NO;
  }

  return YES;
}
\$\endgroup\$
1
  • \$\begingroup\$ You should probably mark this answer as accepted, there's nothing wrong in accepting an answer to your own question. \$\endgroup\$ Commented Oct 1, 2012 at 8:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .