iOS 中的多重采样渲染纹理

7
我正在尝试在启用多重采样的iOS上呈现到纹理,然后在最终输出中使用该纹理。这个可行吗?
到目前为止,我只得到了黑色的纹理或锯齿形图像。我使用的代码是:
  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

这段代码无法正常工作。如果我让深度渲染缓冲区多重采样,它就会失败。如果我只是使用普通的fbo进行深度测试,那么它可以工作,但会产生锯齿状图像。

有人知道我错在哪里吗?

谢谢!


深度缓冲区本身创建失败了吗?也就是说,glRenderbufferStorageMultisampleAPPLE调用失败了吗? - Goz
那个调用没有返回glGetError(),但是glCheckFramebufferStatus()返回GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE。 - ashleysmithgpu
2个回答

15

是的!我找到了我做错的地方。我错误地认为我可以这样做:

帧缓冲区

  • 附加到纹理上的多重采样色彩渲染缓冲区

  • 多重采样深度缓冲区

但你不能这样做。D: 你必须要有以下内容:

多重采样帧缓冲区:

  • 多重采样色彩渲染缓冲区(不附加到纹理上)

  • 多重采样深度渲染缓冲区

普通帧缓冲区:

  • 附加到纹理上的色彩渲染缓冲区。这是将被glResolveMultisampleFramebufferAPPLE()写入并用于呈现结果的内容。

  • 没有深度缓冲区。

也就是说,您必须将多重采样渲染的结果复制到一个全新的帧缓冲区中。

一些代码:

  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

感谢Goz,你让我朝着正确的方向前进!


3

我假设您一直在参考这个页面的示例代码?

请删除glFramebufferTexture2D调用,因为它可能会导致多重采样渲染缓冲区分离,从而您将拥有一个多重采样的后备缓冲区和一个单一采样的渲染缓冲区。此外,创建一个单一采样的深度缓冲区将解决您的问题,因为它将不与那个单一采样的渲染缓冲区匹配。

编辑:您何时遇到错误?是在创建渲染缓冲区时吗?如果是这样,最好按照我发布的链接中的示例代码尝试(我假设您正在使用该链接中的示例代码)。

即:

glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height);

1
我可以通过这些更改使单个采样深度和多采样设置正常工作,但仍然得到黑色纹理。我还发现,以这种方式进行时,glResolveMultisampleFramebufferAPPLE()将会给出GL_INVALID_FRAMEBUFFER_OPERATION。 - ashleysmithgpu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接