glGenFramebuffers 还是 glGenFramebuffersEXT?
我很困惑。要在 Windows 上的 OpenGL 1.x 中使用帧缓冲区对象扩展 (FBO),我应该使用哪一个?:
wglGetProcAddress("glGenFramebuffers");
// or
wglGetProcAddress("glGenFramebuffersEXT");
据我从使用不同硬件的用户的报告来看,某些驱动程序不支持两者的所有组合,其中之一两个,或两者。
哪一个才是正确的使用方式?是否有些驱动程序确实支持其中一种而不支持另一种?如果找不到,尝试从一种方法回退到另一种方法是否正确?
编辑:我仍然遇到 ATI Radeon 卡及其相关代码的严重问题。我们刚刚使用此代码推出了一个商业编辑器 (www.scirra.com)。似乎无论我使用什么代码组合来使用 FBO,某些不同的用户组合都会报告他们根本看不到任何内容(即没有任何渲染)。
下面是我检测是否使用 ARB 函数(无后缀)或 EXT 后缀函数的代码。它在启动时运行:
gl_extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
gl_shading_language = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
// If OpenGL version >= 3, framebuffer objects are core - enable regardless of extension
// (the flags are initialised to false)
if (atof(gl_version) >= 3.0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = false;
}
else
{
// Detect framebuffer object support via ARB (for OpenGL version < 3) - also uses non-EXT names
if (strstr(gl_extensions, "ARB_framebuffer_object") != 0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = false;
}
// Detect framebuffer object support via EXT (for OpenGL version < 3) - uses the EXT names
else if (strstr(gl_extensions, "EXT_framebuffer_object") != 0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = true;
}
}
然后在启动过程中,它会创建一个 FBO 以预期渲染到纹理:
// Render-to-texture support: create a frame buffer object (FBO)
if (support_framebuffer_object)
{
// If support is via EXT (OpenGL version < 3), add the EXT suffix; otherwise functions are core (OpenGL version >= 3)
// or ARB without the EXT suffix, so just get the functions on their own.
std::string suffix = (support_framebuffer_via_ext ? "EXT" : "");
glGenFramebuffers = (glGenFramebuffers_t)wglGetProcAddress((std::string("glGenFramebuffers") + suffix).c_str());
glDeleteFramebuffers = (glDeleteFramebuffers_t)wglGetProcAddress((std::string("glDeleteFramebuffers") + suffix).c_str());
glBindFramebuffer = (glBindFramebuffer_t)wglGetProcAddress((std::string("glBindFramebuffer") + suffix).c_str());
glFramebufferTexture2D = (glFramebufferTexture2D_t)wglGetProcAddress((std::string("glFramebufferTexture2D") + suffix).c_str());
glCheckFramebufferStatus = (glCheckFramebufferStatus_t)wglGetProcAddress((std::string("glCheckFramebufferStatus") + suffix).c_str());
glGenerateMipmap = (glGenerateMipmap_t)wglGetProcAddress((std::string("glGenerateMipmap") + suffix).c_str());
// Create a FBO in anticipation of render-to-texture
glGenFramebuffers(1, &fbo);
}
我已经经历了这段代码的许多变体,但我根本无法让它适用于每个人。总有一群用户报告根本没有任何渲染。 ATI Radeon HD 卡似乎问题尤其严重。我不确定是否涉及驱动程序错误,但我想我上面的代码更有可能做出了错误的假设。
500 代表赏金,我将向任何知道问题所在的人发送免费的营业执照! (价值 99 英镑)
编辑 2:更多细节。以下是已知会失败的显卡列表:
ATI Mobility Radeon HD 5650
ATI Radeon X1600 Pro
ATI Mobility Radeon HD 4200
实际上没有完成纹理渲染。看起来 glGenFramebuffers
调用单独停止在这些卡上完全渲染。我可以将 FBO 的创建推迟到第一次渲染到纹理实际完成时,但随后可能它会再次停止渲染。
我可以使用 GLEW,但是它能做什么而我的代码却不能呢?我查看了源代码,它似乎使用了类似的 wglGetProcAddress
列表。在我的例子中,方法被返回,否则 glGenFramebuffers
将为 NULL 并崩溃。有什么想法吗...?
I'm confused. To use the Framebuffer Object extension (FBO) in OpenGL 1.x on Windows, which of these do I use?:
wglGetProcAddress("glGenFramebuffers");
// or
wglGetProcAddress("glGenFramebuffersEXT");
As far as I can tell from reports from users with different hardware, some drivers support all combinations of neither, one of the two, or both.
Which is the right one to use? Do some drivers really support one but not the other? Is it correct to try to fall back from one to the other if not found?
Edit: I'm still having serious problems with ATI Radeon cards and the code around this. We just launched a commercial editor using this code (www.scirra.com). It seems no matter what combination of code I use to use FBOs, some different combination of users reports they cannot see anything at all (i.e. nothing renders).
Here's the code where I detect whether to use the ARB functions (no suffix) or the EXT-suffixed functions. This runs on startup:
gl_extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
gl_shading_language = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
// If OpenGL version >= 3, framebuffer objects are core - enable regardless of extension
// (the flags are initialised to false)
if (atof(gl_version) >= 3.0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = false;
}
else
{
// Detect framebuffer object support via ARB (for OpenGL version < 3) - also uses non-EXT names
if (strstr(gl_extensions, "ARB_framebuffer_object") != 0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = false;
}
// Detect framebuffer object support via EXT (for OpenGL version < 3) - uses the EXT names
else if (strstr(gl_extensions, "EXT_framebuffer_object") != 0)
{
support_framebuffer_object = true;
support_framebuffer_via_ext = true;
}
}
Then later on during startup it creates a FBO in anticipation of rendering to texture:
// Render-to-texture support: create a frame buffer object (FBO)
if (support_framebuffer_object)
{
// If support is via EXT (OpenGL version < 3), add the EXT suffix; otherwise functions are core (OpenGL version >= 3)
// or ARB without the EXT suffix, so just get the functions on their own.
std::string suffix = (support_framebuffer_via_ext ? "EXT" : "");
glGenFramebuffers = (glGenFramebuffers_t)wglGetProcAddress((std::string("glGenFramebuffers") + suffix).c_str());
glDeleteFramebuffers = (glDeleteFramebuffers_t)wglGetProcAddress((std::string("glDeleteFramebuffers") + suffix).c_str());
glBindFramebuffer = (glBindFramebuffer_t)wglGetProcAddress((std::string("glBindFramebuffer") + suffix).c_str());
glFramebufferTexture2D = (glFramebufferTexture2D_t)wglGetProcAddress((std::string("glFramebufferTexture2D") + suffix).c_str());
glCheckFramebufferStatus = (glCheckFramebufferStatus_t)wglGetProcAddress((std::string("glCheckFramebufferStatus") + suffix).c_str());
glGenerateMipmap = (glGenerateMipmap_t)wglGetProcAddress((std::string("glGenerateMipmap") + suffix).c_str());
// Create a FBO in anticipation of render-to-texture
glGenFramebuffers(1, &fbo);
}
I have been through many variations of this code, and I simply cannot get it to work for everyone. There is always a group of users who report nothing renders at all. ATI Radeon HD cards seem to be particularly problematic. I'm not sure if there's a driver bug involved, but I guess it's more likely my above code is making an incorrect assumption.
500 rep bounty and I'll send a free Business license to anyone who knows what's wrong! (Worth £99)
Edit 2: some more details. Here is a list of cards that this is known to fail on:
ATI Mobility Radeon HD 5650
ATI Radeon X1600 Pro
ATI Mobility Radeon HD 4200
No rendering to texture is actually done. It appears the glGenFramebuffers
call alone stops rendering completely on these cards. I could defer creation of the FBO to the first time render-to-texture is actually done, but then presumably it will just stop rendering again.
I could use GLEW, but what does it do that my code doesn't? I had a look through the source and it seems to use a similar list of wglGetProcAddress
. Methods are being returned in my case, else glGenFramebuffers
would be NULL and crash. Any ideas...?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果存在扩展
GL_EXT_framebuffer_object
,则可以使用wglGetProcAddress("glGenFramebuffersEXT");
。如果 OpenGL 版本 >= 3.0(在此版本中,FBO 扩展已添加到核心),那么您可以使用
wglGetProcAddress("glGenFramebuffers");
。If the extension
GL_EXT_framebuffer_object
is present, then you can usewglGetProcAddress("glGenFramebuffersEXT");
.If the OpenGL version is >= 3.0 (in this version the FBO extension was added to the core), then you can use
wglGetProcAddress("glGenFramebuffers");
.您所包含的代码不是问题。当然,绑定点应该像你已经做的那样获得。
如果支持 ARB_framebuffer_object,则使用不带 EXT 后缀。在支持 EXT_framebuffer_object 的情况下,使用带有 EXT 后缀。如果两者都支持,您可以通过获取正确的绑定点来选择实现。
我对这个问题非常感兴趣(因为我有类似的疑问因为你)。
如果将 ARB 规范与 EXT 规范进行比较,您会发现很多差异。
在这里,我将引用有关该主题的最有趣的ARB规范段落。
该规范很长,但ARB变体包含许多关于EXT兼容性问题的讨论。由于您正在运行应用程序,因此入口点可能是正确的,并且错误(如 Nicolas Bolas 所建议的)可能存在于帧缓冲区完整性中。
介绍每一项可能的检查,并仔细检查实施两次(一次考虑ARB规范,一次考虑EXT规范)。
The code you have included is not the problem. Of course, the binding points shall be obtained as you already do.
In the case ARB_framebuffer_object is supported, uses the entry points without EXT suffix. In the case EXT_framebuffer_object is supported, uses the entry points with EXT suffix. If both are supported, you can select the implementation by getting the right binding points.
I am very interested on this issue (since I had a similar doubt because you).
If you compare the ARB specification with the EXT specification, you can notice a lot of differences.
Here, I will quote the most interesting ARB specification paragraphs on this topic.
The specification is the very long, but the ARB variant contains many discussions on the EXT compatibility issue. Since you're application run, the entry points are probably correct, and the error (as suggested by Nicolas Bolas) could be in the framebuffer completeness.
Introduce every check possible, and double-check the implementation twice (one taking ARB spec in mind, one taking EXT spec in mind).