我打算重写一个小型 C++ OpenGL 字体库,因为我最近发现了对较新 OpenGL 版本的更改,所以我使用 FreeType 2 做了一段时间。我的代码使用立即模式,并且我很确定现在不推荐使用某些函数调用,例如 glLineStipple。
我非常希望支持一系列 OpenGL 版本,以便代码在可能的情况下使用例如 VBO,或者在没有其他可用的情况下回退到立即模式等等。我不知道该怎么做。Afaik,您无法进行编译时检查,因为您需要在运行时创建有效的 OpenGL 上下文。到目前为止,我提出了以下建议(灵感来自其他线程/站点):
使用 GLEW 在绘图函数中进行运行时检查并检查函数支持(例如 glLineStipple)
使用可以在编译时指定的一些 #define 和其他预处理器指令来编译适用于不同 OpenGL 版本的不同版本
编译支持不同 OpenGL 版本的不同版本,并将每个版本作为单独的下载提供
使用脚本 (Python/Perl) 交付库,该脚本检查系统上的 OpenGL 版本(如果可能/可靠)并对源进行适当的修改,使其适合用户的 OpenGL 版本
仅针对较新的 OpenGL 版本并放弃对以下任何内容的支持
无论如何,我可能会使用 GLEW 轻松加载扩展。
跟进: 根据您非常有用的答案,我尝试根据我的旧代码编写几行代码,这是一个片段(未经测试/完成)。我在配置头中声明了适当的函数指针,然后在初始化库时,我尝试获取正确的函数指针。如果 VBO 失败(指针为空),我会退回到显示列表(在 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