我打算重写一段时间后使用的小型C ++ OpenGL字体库 FreeType 2,因为我最近发现了对更新的OpenGL版本的更改。我的代码 使用立即模式和一些函数调用我很确定现在已弃用,例如 glLineStipple。
我非常想支持一系列OpenGL版本,例如代码 使用例如VBO是可能的,或者如果没有其他可用的话,则回退到立即模式 等等。我不知道怎么回事。 Afaik,你不能做一个编译 时间检查,因为您需要在运行时创建有效的OpenGL上下文。到目前为止,我已经 提出以下建议(灵感来自其他线程/网站):
使用GLEW在绘图功能中进行运行时检查并检查功能 支持(例如glLineStipple)
使用一些可以在编译时指定的#define和其他预处理程序指令 是时候编译使用不同OpenGL版本的不同版本了
编译支持不同OpenGL版本的不同版本,并将每个版本作为一个提供 单独下载
使用脚本(Python / Perl)运送库,该脚本检查OpenGL版本 系统(如果可能/可靠)并对源进行适当的修改 所以它符合用户的OpenGL版本
仅定位较新的OpenGL版本,并放弃对
我可能无论如何都会使用GLEW轻松加载扩展程序。
后续: 基于你非常有用的答案,我尝试根据我的旧代码添加几行,这里是一个片段(没有测试/完成)。我在config头中声明了相应的函数指针,然后在初始化库时,我尝试获得正确的函数指针。如果VBO失败(指针为null),我会回到显示列表(不推荐使用3.0),最后回到顶点数组。如果是fx,我应该(也许?)检查可用的ARB扩展名。 VBO无法加载或太多工作?这会是一个坚实的批评吗?评论赞赏:)
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#define OFL_WINDOWS
// other stuff...
#ifndef OFL_USES_GLEW
// Check which extensions are supported
#else
// Declare vertex buffer object extension function pointers
PFNGLGENBUFFERSPROC glGenBuffers = NULL;
PFNGLBINDBUFFERPROC glBindBuffer = NULL;
PFNGLBUFFERDATAPROC glBufferData = NULL;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = NULL;
PFNGLDELETEBUFFERSPROC glDeleteBuffers = NULL;
PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements = NULL;
PFNGLBUFFERSUBDATAPROC glBufferSubData = NULL;
PFNGLMAPBUFFERPROC glMapBuffer = NULL;
PFNGLUNMAPBUFFERPROC glUnmapBuffer = NULL;
#endif
#elif some_other_system
初始化功能:
#ifdef OFL_WINDOWS
bool loaded = true;
// Attempt to load vertex buffer obejct extensions
loaded = ((glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers")) != NULL && loaded);
loaded = ((glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer")) != NULL && loaded);
loaded = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer")) != NULL && loaded);
loaded = ((glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress("glDeleteBuffers")) != NULL && loaded);
loaded = ((glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)wglGetProcAddress("glMultiDrawElements")) != NULL && loaded);
loaded = ((glBufferSubData = (PFNGLBUFFERSUBDATAPROC)wglGetProcAddress("glBufferSubData")) != NULL && loaded);
loaded = ((glMapBuffer = (PFNGLMAPBUFFERPROC)wglGetProcAddress("glMapBuffer")) != NULL && loaded);
loaded = ((glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)wglGetProcAddress("glUnmapBuffer")) != NULL && loaded);
if (!loaded)
std::cout << "OFL: Current OpenGL context does not support vertex buffer objects" << std::endl;
else {
#define OFL_USES_VBOS
std::cout << "OFL: Loaded vertex buffer object extensions successfully"
return true;
}
if (glMajorVersion => 3.f) {
std::cout << "OFL: Using vertex arrays" << std::endl;
#define OFL_USES_VERTEX_ARRAYS
} else {
// Display lists were deprecated in 3.0 (although still available through ARB extensions)
std::cout << "OFL: Using display lists"
#define OFL_USES_DISPLAY_LISTS
}
#elif some_other_system
答案 0 :(得分:5)
首先,你可以安全地使用那个,因为它在任何地方都受到支持:重写你的字体渲染器以使用 Vertex Arrays 。从VAs到VBO只是一小步,但各地都支持VA。您只需要一小组扩展功能;也许手动加载是有意义的,不依赖于GLEW。静态链接它是一个巨大的过度杀伤。
然后将调用放入包装器函数中,您可以通过函数指针引用它们,以便您可以通过这种方式切换渲染路径。例如,添加一个函数“stipple_it”左右,并在内部调用glLineStipple或构建并为其设置适当的片段着色器。
类似于glVertexPointer与glVertexAttribPointer。
答案 1 :(得分:3)
如果您确实希望手动进行每次检查,那么您将无法摆脱某些#defines,因为Android / iOS仅支持OpenGL ES,然后运行时检查会有所不同。
运行时检查也几乎是不可避免的,因为(根据个人经验),不同硬件供应商的驱动程序存在很多警告(当然,对于OpenGL 1.0以上的任何内容)。
“仅针对较新的OpenGL版本并放弃对以下任何内容的支持”将是一个可行的选择,因为ATI / nVidia甚至英特尔的大多数视频卡都支持某些版本的OpenGL 2.0+,这大致相当于GL ES 2.0
GLEW是一种简化GL扩展提取的好方法。但是,GL ES在嵌入式平台上存在问题。
现在加载程序:
在win32 / linux上,只需检查函数指针是否为NULL,并使用GL的ExtensionString来了解此具体硬件支持的内容
iOS / Android / MacOSX的“加载”只是存储指针甚至是“无所事事”。 Android是一个不同的野兽,这里你有静态指针,但需要检查扩展名。即使经过这些检查,您可能也不确定某些报告为“正常工作”的事情(我说的是“非名称”Android设备或简单的gfx硬件)。因此,您将根据显卡的名称添加自己的(!)检查。
OSX / iOS OpenGL实现“正常”。所以,如果你在10.5上运行,你将获得GL2.1; 10.6 - 2.1 +一些扩展使它几乎像3.1 / 3.2; 10.7 - 3.2 CoreProfile。目前没有适用于Mac的GL4.0,这主要是3.2的演变。
如果你对我的个人意见感兴趣,那么我主要来自“重塑一切”阵营,多年来我们一直在使用一些自动生成的扩展装载机。
最重要的是,你走在正确的轨道上:重写VBO / VA / Shaders / NoFFP会给你带来重大的性能提升。