OpenGL Loading Library: Difference between revisions
No edit summary |
EdgarCaswell (talk | contribs) Add Example how to fetch and setup glad via CMake |
||
(16 intermediate revisions by 11 users not shown) | |||
Line 2: | Line 2: | ||
Most extension loading libraries override the need to include gl.h at all. Instead, they provide their own header that must be used. Most extension loading libraries use code generation to construct the code that loads the function pointers and the included headers. Information is available if you wish to [[Load OpenGL Functions|perform this manually]], but you are encouraged to use one of these libraries yourself. | Most extension loading libraries override the need to include gl.h at all. Instead, they provide their own header that must be used. Most extension loading libraries use code generation to construct the code that loads the function pointers and the included headers. Information is available if you wish to [[Load OpenGL Functions|perform this manually]], but you are encouraged to use one of these libraries yourself. | ||
== glad (Multi-Language GL/GLES/EGL/GLX/WGL Loader-Generator) == | |||
[https://github.com/Dav1dde/glad Glad] generates a loader for your exact needs based on the official OpenGL specifications. This means they are always up to date! It was written in a way that you can easily extend it to other languages. | |||
You can use the [http://glad.dav1d.de/ glad website] to generate a loader for your needs, download it and use it in your project. Another method of using glad is cloning/downloading the repository and generating your own loader. The tool itself is pretty easy to use and works with any Python version above 2.6, you can also include the source directly into your CMake project. | |||
Glad gives you the option to also generate a very basic loader, but it is recommended to use the loading function provided by your context creation framework, like ''glfwGetProcAddress''. | |||
Here is how it looks: | |||
<source lang="cpp"> | |||
#include <glad/gl.h> | |||
// GLFW (include after glad) | |||
#include <GLFW/glfw3.h> | |||
int main() { | |||
// -- snip -- | |||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", NULL, NULL); | |||
glfwMakeContextCurrent(window); | |||
int version = gladLoadGL(glfwGetProcAddress); | |||
if (version == 0) { | |||
printf("Failed to initialize OpenGL context\n"); | |||
return -1; | |||
} | |||
// Successfully loaded OpenGL | |||
printf("Loaded OpenGL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); | |||
// -- snip -- | |||
} | |||
</source> | |||
Glad is able to generate a debugging header, which allows you to hook into your OpenGL calls really easily using ''glad_set_pre_callback'' and ''glad_set_post_callback'', you can find a more detailed guide on the [https://github.com/Dav1dde/glad#cc-debug github repository]. | |||
If you use '''CMake''' already. Here is how you can use its FetchContent capability to add Glad to your project. | |||
<source lang="cmake"> | |||
include(FetchContent) | |||
FetchContent_Declare( | |||
glad | |||
GIT_REPOSITORY https://github.com/Dav1dde/glad | |||
GIT_TAG v2.0.6 | |||
GIT_SHALLOW TRUE | |||
GIT_PROGRESS TRUE | |||
) | |||
FetchContent_GetProperties(glad) | |||
if(NOT glad_POPULATED) | |||
message("Fetching glad") | |||
FetchContent_MakeAvailable(glad) | |||
add_subdirectory("${glad_SOURCE_DIR}/cmake" glad_cmake) | |||
glad_add_library(glad REPRODUCIBLE EXCLUDE_FROM_ALL LOADER API gl:core=4.6 EXTENSIONS GL_ARB_bindless_texture GL_EXT_texture_compression_s3tc) | |||
endif() | |||
</source> | |||
and link glad with your project via | |||
<source lang="cmake"> | |||
target_link_libraries(YourProject | |||
... | |||
PRIVATE glad::glad | |||
... | |||
) | |||
</source> | |||
== glbinding (C++) == | |||
[https://github.com/hpicgs/glbinding ''glbinding''] is a new, generated, cross-platform C++ binding for OpenGL which is solely based on the new xml-based OpenGL API specification (gl.xml). It leverages modern C++11 features like enum classes, lambdas, and variadic templates, instead of relying on macros (all OpenGL symbols are real functions and variables). It provides type-safe parameters, per feature API header, lazy function resolution, multi-context and multi-thread support, global function callbacks, meta information about the generated OpenGL binding and the OpenGL runtime, as well as multiple examples for quick-starting your projects. | |||
Current gl code, written with a typical C binding for OpenGL is fully compatible for the use with glbinding: | |||
<source lang="cpp"> | |||
#include <glbinding/gl/gl.h> | |||
#include <glbinding/Binding.h> | |||
using namespace gl; | |||
int main() | |||
{ | |||
// create context, e.g. using GLFW, Qt, SDL, GLUT, ... | |||
glbinding::Binding::initialize(); | |||
glBegin(GL_TRIANGLES); | |||
// ... | |||
glEnd(); | |||
} | |||
</source> | |||
''glbinding'' also supports OpenGL feature (version) specific symbols for functions, enums, and bitfields. For example: | |||
* functions32.h provides all OpenGL commands available up to 3.2 in namespace gl32. | |||
* functions32core.h provides all non-deprecated OpenGL commands available up to 3.2 in namespace gl32core. | |||
* functions32ext.h provides all OpenGL commands specified either in 3.3 and above, or by extension in gl32ext. | |||
More details and examples can be found on the [https://github.com/hpicgs/glbinding github project page] and [https://github.com/hpicgs/glbinding/wiki/examples examples wiki] respectively. | |||
== GLEW (OpenGL Extension Wrangler) == | == GLEW (OpenGL Extension Wrangler) == | ||
Line 7: | Line 106: | ||
The [http://glew.sourceforge.net/ OpenGL Extension Wrangler] library provides access to all GL entrypoints. It supports Windows, MacOS X, Linux, and FreeBSD. | The [http://glew.sourceforge.net/ OpenGL Extension Wrangler] library provides access to all GL entrypoints. It supports Windows, MacOS X, Linux, and FreeBSD. | ||
GLEW has a problem with core contexts. It calls {{apifunc|glGetString|(GL_EXTENSIONS)}}, which causes {{enum|GL_INVALID_ENUM}} on GL 3.2+ core context as soon as {{code|glewInit()}} is called. It also doesn't fetch the function pointers. | As with most other loaders, you should not include {{code|gl.h}}, {{code|glext.h}}, or any other gl related header file before {{code|glew.h}}, otherwise you'll get an error message that you have included {{code|gl.h}} before {{code|glew.h}}. In fact, you shouldn't be including {{code|gl.h}} at all; {{code|glew.h}} replaces it. | ||
GLEW also provides {{code|wglew.h}} which provides Windows specific GL functions (wgl functions). If you include {{code|wglext.h}} before {{code|wglew.h}}, GLEW will complain. GLEW also provides {{code|glxew.h}} for X windows systems. If you include {{code|glxext.h}} before {{code|glxew.h}}, GLEW will complain. | |||
The latest release as of June 2021 is version 2.2.0. | |||
=== Initialization of GLEW 1.13.0 and earlier === | |||
GLEW up to version 1.13.0 has a problem with core contexts. It calls {{apifunc|glGetString|(GL_EXTENSIONS)}}, which causes {{enum|GL_INVALID_ENUM}} on GL 3.2+ core context as soon as {{code|glewInit()}} is called. It also doesn't fetch the function pointers. GLEW version 2.0.0+ uses {{apifunc|glGetString|i}} instead. The only fix for earlier versions is to use {{code|glewExperimental}}: | |||
<source lang="cpp"> | <source lang="cpp"> | ||
// If using GLEW version 1.13 or earlier | |||
glewExperimental=TRUE; | glewExperimental=TRUE; | ||
GLenum err=glewInit(); | GLenum err=glewInit(); | ||
if(err!=GLEW_OK) | if(err!=GLEW_OK) { | ||
// Problem: glewInit failed, something is seriously wrong. | |||
//Problem: glewInit failed, something is seriously wrong. | cout << "glewInit failed: " << glewGetErrorString(err) << endl; | ||
cout<<"glewInit failed | exit(1); | ||
} | } | ||
</source> | </source> | ||
Line 23: | Line 131: | ||
You might still get GL_INVALID_ENUM (depending on the version of GLEW you use), but at least GLEW ignores {{apifunc|glGetString|(GL_EXTENSIONS)}} and gets all function pointers. | You might still get GL_INVALID_ENUM (depending on the version of GLEW you use), but at least GLEW ignores {{apifunc|glGetString|(GL_EXTENSIONS)}} and gets all function pointers. | ||
If you are creating a GL context the old way or if you are creating a backward compatible context for GL 3.2+, then you don't need | If you are creating a GL context the old way or if you are creating a backward compatible context for GL 3.2+, then you don't need {{code|glewExperimental}}. | ||
== GL3W == | == GL3W == | ||
Line 33: | Line 137: | ||
The [https://github.com/skaslev/gl3w GL3W] library focuses on the core profile of OpenGL 3 and 4. It only loads the core entrypoints for these OpenGL versions. It supports Windows, Mac OS X, Linux, and FreeBSD. | The [https://github.com/skaslev/gl3w GL3W] library focuses on the core profile of OpenGL 3 and 4. It only loads the core entrypoints for these OpenGL versions. It supports Windows, Mac OS X, Linux, and FreeBSD. | ||
{{note|GL3W | {{note|GL3W loads core OpenGL ''only'' by default. All OpenGL extensions will be loaded if the {{code|--ext}} flag is specified to {{code|gl3w_gen.py}}.}} | ||
GL3W relies on a Python script for its code generation. Unlike other extension loaders, GL3W actually does the code generation on your machine. This is based on downloading and parsing the {{code|glcorearb.h}} file from the OpenGL Registry website. | GL3W relies on a Python script for its code generation. Unlike other extension loaders, GL3W actually does the code generation on your machine. This is based on downloading and parsing the {{code|glcorearb.h}} file from the OpenGL Registry website. | ||
Line 44: | Line 148: | ||
#include <GL/gl3w.h> | #include <GL/gl3w.h> | ||
#include <GLFW/glfw3.h> | #include <GLFW/glfw3.h> | ||
int main() { | int main() { | ||
Line 55: | Line 157: | ||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | ||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||
Line 77: | Line 178: | ||
</source> | </source> | ||
== | ==Galogen== | ||
[https://galogen.gpfault.net Galogen] is a GL loader generator in the spirit of glLoadGen, but with no additional dependencies (like Lua). Given an API version and a list of extensions, Galogen will produce corresponding headers and code that load the exact OpenGL entry points you need. The produced code can then be used directly by your C or C++ application, without having to link against any additional libraries. Galogen uses the official [https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/gl.xml Khronos OpenGL Registry] as its source of truth, thus ensuring that the produced code always corresponds to the latest specifications. An [http://galogen.gpfault.net/galogen-web.html in-browser version] of Galogen is also available. | |||
== Glatter == | |||
[https://github.com/imakris/glatter Glatter] is a generated library, with support for GL, GLES, GLU, EGL, GLX, WGL. | |||
Its usage requires the inclusion of one header: | |||
<source lang="cpp"> | <source lang="cpp"> | ||
#include <glatter.h> | |||
#include < | </source> | ||
In C++ code, it may as well be used as header-only. | |||
It requires no explicit loading or initialization calls, and its startup cost is minimal. | |||
Besides loading, it offers debugging and tracing functionality. | |||
More details can be found on its [http://github.com/imakris/glatter github] page. | |||
== glsdk (Unofficial OpenGL SDK) == | == glsdk (Unofficial OpenGL SDK) == | ||
Line 193: | Line 251: | ||
} | } | ||
</source> | </source> | ||
== libepoxy == | == libepoxy == |
Latest revision as of 10:09, 20 July 2024
An OpenGL Loading Library is a library that loads pointers to OpenGL functions at runtime, core as well as extensions. This is required to access functions from OpenGL versions above 1.1 on most platforms. Extension loading libraries also abstracts away the difference between the loading mechanisms on different platforms.
Most extension loading libraries override the need to include gl.h at all. Instead, they provide their own header that must be used. Most extension loading libraries use code generation to construct the code that loads the function pointers and the included headers. Information is available if you wish to perform this manually, but you are encouraged to use one of these libraries yourself.
glad (Multi-Language GL/GLES/EGL/GLX/WGL Loader-Generator)
Glad generates a loader for your exact needs based on the official OpenGL specifications. This means they are always up to date! It was written in a way that you can easily extend it to other languages.
You can use the glad website to generate a loader for your needs, download it and use it in your project. Another method of using glad is cloning/downloading the repository and generating your own loader. The tool itself is pretty easy to use and works with any Python version above 2.6, you can also include the source directly into your CMake project.
Glad gives you the option to also generate a very basic loader, but it is recommended to use the loading function provided by your context creation framework, like glfwGetProcAddress.
Here is how it looks:
#include <glad/gl.h>
// GLFW (include after glad)
#include <GLFW/glfw3.h>
int main() {
// -- snip --
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
int version = gladLoadGL(glfwGetProcAddress);
if (version == 0) {
printf("Failed to initialize OpenGL context\n");
return -1;
}
// Successfully loaded OpenGL
printf("Loaded OpenGL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
// -- snip --
}
Glad is able to generate a debugging header, which allows you to hook into your OpenGL calls really easily using glad_set_pre_callback and glad_set_post_callback, you can find a more detailed guide on the github repository.
If you use CMake already. Here is how you can use its FetchContent capability to add Glad to your project.
include(FetchContent)
FetchContent_Declare(
glad
GIT_REPOSITORY https://github.com/Dav1dde/glad
GIT_TAG v2.0.6
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_GetProperties(glad)
if(NOT glad_POPULATED)
message("Fetching glad")
FetchContent_MakeAvailable(glad)
add_subdirectory("${glad_SOURCE_DIR}/cmake" glad_cmake)
glad_add_library(glad REPRODUCIBLE EXCLUDE_FROM_ALL LOADER API gl:core=4.6 EXTENSIONS GL_ARB_bindless_texture GL_EXT_texture_compression_s3tc)
endif()
and link glad with your project via
target_link_libraries(YourProject
...
PRIVATE glad::glad
...
)
glbinding (C++)
glbinding is a new, generated, cross-platform C++ binding for OpenGL which is solely based on the new xml-based OpenGL API specification (gl.xml). It leverages modern C++11 features like enum classes, lambdas, and variadic templates, instead of relying on macros (all OpenGL symbols are real functions and variables). It provides type-safe parameters, per feature API header, lazy function resolution, multi-context and multi-thread support, global function callbacks, meta information about the generated OpenGL binding and the OpenGL runtime, as well as multiple examples for quick-starting your projects.
Current gl code, written with a typical C binding for OpenGL is fully compatible for the use with glbinding:
#include <glbinding/gl/gl.h>
#include <glbinding/Binding.h>
using namespace gl;
int main()
{
// create context, e.g. using GLFW, Qt, SDL, GLUT, ...
glbinding::Binding::initialize();
glBegin(GL_TRIANGLES);
// ...
glEnd();
}
glbinding also supports OpenGL feature (version) specific symbols for functions, enums, and bitfields. For example:
- functions32.h provides all OpenGL commands available up to 3.2 in namespace gl32.
- functions32core.h provides all non-deprecated OpenGL commands available up to 3.2 in namespace gl32core.
- functions32ext.h provides all OpenGL commands specified either in 3.3 and above, or by extension in gl32ext.
More details and examples can be found on the github project page and examples wiki respectively.
GLEW (OpenGL Extension Wrangler)
The OpenGL Extension Wrangler library provides access to all GL entrypoints. It supports Windows, MacOS X, Linux, and FreeBSD.
As with most other loaders, you should not include gl.h, glext.h, or any other gl related header file before glew.h, otherwise you'll get an error message that you have included gl.h before glew.h. In fact, you shouldn't be including gl.h at all; glew.h replaces it.
GLEW also provides wglew.h which provides Windows specific GL functions (wgl functions). If you include wglext.h before wglew.h, GLEW will complain. GLEW also provides glxew.h for X windows systems. If you include glxext.h before glxew.h, GLEW will complain.
The latest release as of June 2021 is version 2.2.0.
Initialization of GLEW 1.13.0 and earlier
GLEW up to version 1.13.0 has a problem with core contexts. It calls glGetString(GL_EXTENSIONS), which causes GL_INVALID_ENUM on GL 3.2+ core context as soon as glewInit() is called. It also doesn't fetch the function pointers. GLEW version 2.0.0+ uses glGetStringi instead. The only fix for earlier versions is to use glewExperimental:
// If using GLEW version 1.13 or earlier
glewExperimental=TRUE;
GLenum err=glewInit();
if(err!=GLEW_OK) {
// Problem: glewInit failed, something is seriously wrong.
cout << "glewInit failed: " << glewGetErrorString(err) << endl;
exit(1);
}
glewExperimental is a variable that is already defined by GLEW. You must set it to GL_TRUE before calling glewInit().
You might still get GL_INVALID_ENUM (depending on the version of GLEW you use), but at least GLEW ignores glGetString(GL_EXTENSIONS) and gets all function pointers.
If you are creating a GL context the old way or if you are creating a backward compatible context for GL 3.2+, then you don't need glewExperimental.
GL3W
The GL3W library focuses on the core profile of OpenGL 3 and 4. It only loads the core entrypoints for these OpenGL versions. It supports Windows, Mac OS X, Linux, and FreeBSD.
GL3W relies on a Python script for its code generation. Unlike other extension loaders, GL3W actually does the code generation on your machine. This is based on downloading and parsing the glcorearb.h file from the OpenGL Registry website.
On the one hand, this means that it is always up-to-date. On the other hand, this also makes it beholden to the format of glcorearb.h (which has no true format), as well as requiring that the user of GL3W have a Python installation.
GL3W is used like this:
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
int main() {
if (!glfwInit()) {
printf("failed to initialize GLFW.\n");
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
auto window = glfwCreateWindow(1000, 600, "awesome", nullptr, nullptr);
if (!window) {
return -1;
}
glfwMakeContextCurrent(window);
if (gl3wInit()) {
printf("failed to initialize OpenGL\n");
return -1;
}
printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
// ...
return 0;
}
Galogen
Galogen is a GL loader generator in the spirit of glLoadGen, but with no additional dependencies (like Lua). Given an API version and a list of extensions, Galogen will produce corresponding headers and code that load the exact OpenGL entry points you need. The produced code can then be used directly by your C or C++ application, without having to link against any additional libraries. Galogen uses the official Khronos OpenGL Registry as its source of truth, thus ensuring that the produced code always corresponds to the latest specifications. An in-browser version of Galogen is also available.
Glatter
Glatter is a generated library, with support for GL, GLES, GLU, EGL, GLX, WGL.
Its usage requires the inclusion of one header:
#include <glatter.h>
In C++ code, it may as well be used as header-only.
It requires no explicit loading or initialization calls, and its startup cost is minimal.
Besides loading, it offers debugging and tracing functionality.
More details can be found on its github page.
glsdk (Unofficial OpenGL SDK)
The Unofficial OpenGL SDK includes a component for loading OpenGL functions. This component, called GL Load, has a C and C++ interface for loading OpenGL functions. It also provides different headers for different OpenGL versions. It even has headers that remove compatibility enums and functions for versions of OpenGL 3.1 or greater.
Here is a code example:
#include <glload/gl_3_3.h> //OpenGL version 3.3, core profile. C-style functions.
#include <glload/gll.h> //The C-style loading interface.
//Include headers for FreeGLUT/GLFW/other GL tools.
int main(int argc, char *argv[])
{
//Initialize OpenGL and bind the context
if(LoadFunctions() == LS_LOAD_FAILED)
//exit in some way
//Loading succeeded. Now use OpenGL functions.
//Do OpenGL stuff.
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
...
}
GL Load even offers special headers for C++ code, that moves as much of OpenGL as possible into a namespace. The equivalent code in the C++ interface is as follows:
#include <glload/gl_3_3.hpp> //OpenGL version 3.3, core profile. C++-style functions.
#include <glload/gll.hpp> //The C-style loading interface.
//Include headers for FreeGLUT/GLFW/other GL tools.
int main(int argc, char *argv[])
{
//Initialize OpenGL and bind the context
if(glload::LoadFunctions() == glload::LS_LOAD_FAILED)
//exit in some way
//Loading succeeded. Now use OpenGL functions.
//Do OpenGL stuff.
GLuint vertShader = gl::CreateShader(gl::GL_VERTEX_SHADER);
GLuint fragShader = gl::CreateShader(gl::GL_FRAGMENT_SHADER);
...
}
libepoxy
libepoxy requires no initialization code. The only thing you have to do is:
#include <epoxy/gl.h>
#include <epoxy/glx.h>
GLee
The project seems more or less defunct.
While there is activity in the Git repository on Sourceforge, there has not been a new official version and distribution in years. The recent activity could represent a project coming back, but currently you would be better advised to look elsewhere for an OpenGL loader.