Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multisampled render to texture in ios

I am attempting to render to a texture in ios with multisampling enabled and then use that texture in my final output. Is this possible?

So far I have only gotten black textures or aliased images. The code I am using is:

  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

  glGenFramebuffers(1, &framebuffer);
  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

  glGenRenderbuffers(1, &colorRenderbuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  //glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, width, height);
  glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA4, width, height);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

  glGenRenderbuffers(1, &depthRenderbuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
  //glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, self.view.bounds.size.height);
  glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

  GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
  if(status != GL_FRAMEBUFFER_COMPLETE) {
    NSLog(@"failed to make complete framebuffer object %x", status);
  }

  // Render my scene

  glBindFramebuffer( GL_FRAMEBUFFER, framebuffer );
  glViewport(0,0,width,height);
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  // Draw scene

  // Then bind default framebuffer

  glBindFramebuffer( GL_FRAMEBUFFER, 1 );

  // Draw other things

  // Now resolve the multisampling and draw texture

  glResolveMultisampleFramebufferAPPLE();

  glUseTexture( GL_TEXTURE_2D, texture );

  // Draw with texture

This code does not work. It fails if I make the depth render buffer multisampled. If I just use a normal fbo for the depth then it works, but produces an aliased image.

Anyone know where I am going wrong?

Thanks!

like image 698
ashleysmithgpu Avatar asked Sep 13 '11 13:09

ashleysmithgpu


1 Answers

Yes! I found what I was doing wrong. I wrongly thought that I could have the following:

Framebuffer

  • Multisampled colour render buffer attached to a texture

  • Multisampled depth buffer

But you cannot do this. D: You have to have the following:

Multisampled framebuffer:

  • Multisampled colour render buffer (Not attached to a texture)

  • Multisampled depth render buffer

Normal framebuffer:

  • Colour render buffer attached to a texture. This is what will be written to by glResolveMultisampleFramebufferAPPLE() and what we will use to render the result.

  • No depth buffer.

I.e. you have to copy the results of the multisampled render to a whole new framebuffer.

Some code:

  glGenTextures(1, &texture);
  glBindTexture(GL_TEXTURE_2D, texture);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

  glGenFramebuffers(1, &resolved_framebuffer);
  glBindFramebuffer(GL_FRAMEBUFFER, resolved_framebuffer);
  glGenRenderbuffers(1, &resolvedColorRenderbuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, resolvedColorRenderbuffer);
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

  glGenFramebuffers(1, &framebuffer);
  glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

  glGenRenderbuffers(1, &colorRenderbuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
  glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

  glGenRenderbuffers(1, &depthRenderbuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
  glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

  GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
  if(status != GL_FRAMEBUFFER_COMPLETE) {
    NSLog(@"failed to make complete framebuffer object %x", status);
  }

  // Render my scene

  glBindFramebuffer( GL_FRAMEBUFFER, framebuffer );
  glViewport(0,0,width,height);
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  // Draw scene

  // Then bind default framebuffer

  glBindFramebuffer( GL_FRAMEBUFFER, 1 );

  // Draw other things

  // Now resolve the multisampling into the other fbo

  glBindFramebuffer( GL_READ_FRAMEBUFFER_APPLE, framebuffer );
  glBindFramebuffer( GL_DRAW_FRAMEBUFFER_APPLE, resolved_framebuffer );

  glResolveMultisampleFramebufferAPPLE();

  glBindTexture( GL_TEXTURE_2D, texture );

  // Draw with texture

Thanks Goz, you got me in the right direction!

like image 53
ashleysmithgpu Avatar answered Oct 19 '22 05:10

ashleysmithgpu