如何找到有效的 OpenGL 帧缓冲区配置/文档
Posted
技术标签:
【中文标题】如何找到有效的 OpenGL 帧缓冲区配置/文档【英文标题】:How to find valid OpenGL framebuffer configuration/documentation 【发布时间】:2017-04-10 16:19:12 【问题描述】:我使用的是 2011 年初的 MacBook Pro,装有 macOS Sierra 10.12.4 和 Intel HD Graphics 3000 512 MB,并且我使用的是 JOGL。根据OS X 10.9 Core Profile OpenGL Information(不幸的是,他们还没有更新版本的信息),我的系统支持 0、16 或 24 bpp 深度缓冲区和 0 或 8 bpp 模板缓冲区。然而,我创建用户帧缓冲区时的实际工作似乎是任何人的猜测:
我可以让它与GL_DEPTH_COMPONENT_32
渲染缓冲区一起工作。
我无法让它与GL_STENCIL_INDEX8
渲染缓冲区一起工作——无论我使用的是16 位、24 位还是32 位深度缓冲区,我总是会收到GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
或GL_FRAMEBUFFER_UNSUPPORTED
错误。
但我可以让它与 GL_DEPTH24_STENCIL8
渲染缓冲区一起使用。
我无法在任何地方找到针对 OS X 的 GL_DEPTH24_STENCIL8
的具体提及。我想确保我的程序可以在各种系统上运行(包括 Windows 和 Linux,因为它是一个 JOGL 应用程序),但似乎我所能做的就是猜测并检查各种帧缓冲区配置,直到找到一个可行的.
真的没有更好的方法来决定使用什么帧缓冲区配置吗?有没有我没有找到的更好文档的网站?供应商是否因为某种原因难以记录?
代码示例
配置失败 int[] temps = new int[3];
this.width = width;
this.height = height;
gl3.glGenFramebuffers(1, temps, 0);
framebuffer = temps[0];
gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);
int numBuffers = 2;
if (desiredUseStencilBuffer)
numBuffers++;
gl3.glGenRenderbuffers(numBuffers, temps, 0);
colorBuffer = temps[0];
depthBuffer = temps[1];
stencilBuffer = temps[2];
numSamples = targetNumSamples;
useStencilBuffer = desiredUseStencilBuffer;
if (numSamples > 1)
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH_COMPONENT24, width, height);
if (useStencilBuffer)
gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL3.GL_STENCIL_INDEX8, width, height);
else
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT24, width, height);
if (useStencilBuffer)
gl3.glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL3.GL_STENCIL_INDEX8,
width, height);
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer)
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencilBuffer);
int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status)
case GL.GL_FRAMEBUFFER_COMPLETE:
break;
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new RuntimeException("An attachment could not be bound to frame buffer object!");
配置成功
int[] temps = new int[3];
this.width = width;
this.height = height;
gl3.glGenFramebuffers(1, temps, 0);
framebuffer = temps[0];
gl3.glBindFramebuffer(GL.GL_FRAMEBUFFER, framebuffer);
gl3.glGenRenderbuffers(2, temps, 0);
colorBuffer = temps[0];
depthBuffer = temps[1];
numSamples = targetNumSamples;
useStencilBuffer = desiredUseStencilBuffer;
if (numSamples > 1)
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL.GL_RGBA8,
width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer)
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH24_STENCIL8, width, height);
else
gl3.glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples,
GL.GL_DEPTH_COMPONENT32, width, height);
else
gl3.glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_RGBA8, width, height);
gl3.glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
if (useStencilBuffer)
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8,
width, height);
else
gl3.glRenderbufferStorage(GL_RENDERBUFFER, GL.GL_DEPTH_COMPONENT32,
width, height);
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
if (useStencilBuffer)
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL2ES3.GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
else
gl3.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthBuffer);
int status = gl3.glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status)
case GL.GL_FRAMEBUFFER_COMPLETE:
break;
case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
throw new RuntimeException("An attachment could not be bound to frame buffer object!");
...
【问题讨论】:
【参考方案1】:OpenGL 规范不要求您可以将单独的深度和模板图像附加到帧缓冲区。 API 允许您尝试它,但个别实现可以通过为您提供不受支持的完成状态来选择禁止它。
3.0 规范添加了required image formats 的概念,其实现为required to accept 用于它们的帧缓冲配置。其中有GL_DEPTH24_STENCIL8
。因此,需要任何兼容的 OpenGL 实现来支持组合的深度/模板缓冲区。
【讨论】:
谢谢,很高兴知道。何时(如果有)通常使用单独的模板附件?在他们自己单独的帧缓冲区中? @Andy:它们不是“常用的”。它们仅在需要时使用:当您渲染到不需要深度缓冲区的东西时。以上是关于如何找到有效的 OpenGL 帧缓冲区配置/文档的主要内容,如果未能解决你的问题,请参考以下文章
来自 OpenGL ES 帧缓冲区 (iOS) 的 CGImageRef
实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码