I'm trying to render to a HWND window using a HGLRC OpenGL rendering context.
I have to initiate the glad but gladLoadGLLoader((GLADloadproc)wglGetProcAddress)) and the gladLoadGL() seems to be failing.
glad OpenGL version : 4.0 core
I've been using the glfwGetProcAdress function until now.
How can I make the gladLoadGLLoader function work? Would it be that I have to indicate the version of the OpenGL to the wglGetProcAddress function or maybe I should use another loader?
Update 1 :
in the gladLoadGLLoader function the problem is (PFNGLGETSTRINGPROC)load("glGetString") returns null
int gladLoadGLLoader(GLADloadproc load) {
GLVersion.major = 0; GLVersion.minor = 0;
glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
if(glGetString == NULL) //Returns there (fails)
return 0;
if(glGetString(GL_VERSION) == NULL)
return 0;
find_coreGL();
load_GL_VERSION_1_0(load);
load_GL_VERSION_1_1(load);
load_GL_VERSION_1_2(load);
load_GL_VERSION_1_3(load);
load_GL_VERSION_1_4(load);
load_GL_VERSION_1_5(load);
load_GL_VERSION_2_0(load);
load_GL_VERSION_2_1(load);
load_GL_VERSION_3_0(load);
load_GL_VERSION_3_1(load);
load_GL_VERSION_3_2(load);
load_GL_VERSION_3_3(load);
if (!find_extensionsGL()) return 0;
return GLVersion.major != 0 || GLVersion.minor != 0;
}
Update 2 :
The problem seems to be that wglGetProcAddress is being used to load core OpenGL functions. However, wglGetProcAddress can only load specific WGL extensions and not core OpenGL stuff.
Update 3 :
As an additional note to the update 2, it seems that the GLFW library also uses wglGetProcAddress for the glfwGetProcAddress function
Solved :
void *GetAnyGLFuncAddress(const char *name)
{
void *p = (void *)wglGetProcAddress(name);
if(p == 0 ||
(p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
(p == (void*)-1) )
{
HMODULE module = LoadLibraryA("opengl32.dll");
p = (void *)GetProcAddress(module, name);
}
return p;
}
void Renderer::initGlad(){
//Init GLAD
if (!gladLoadGLLoader((GLADloadproc)GetAnyGLFuncAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
}
}
Replacing wglGetProcAddress with the void *GetAnyGLFuncAddress(const char *name) function solves the problem.
"The problem seems to be that
wglGetProcAddressis being used to load core OpenGL functions. However,wglGetProcAddresscan only load specific WGL extensions and not core OpenGL stuff." Indeed,wglGetProcAddressdoes have limitations. But it can load OpenGL functions - in fact, most all of them. The restriction is on loading extremely old GL functions that date back to OpenGL 1.1. This is the reason whyglGetStringis null - it's an OpenGL 1.1 function, which isn't supported by it.Fortunately, these age-old functions are the ones that happen to be directly exported by the Windows libary
opengl32.dllitself. Therefore, you can use the Windows functionGetProcAddressonopengl32.dllfor these functions. HoweverGetProcAddress, of course, does not work on newer GL functions.But we can create a new function to 'bridge the gap' between these two:
This function, as you can see, first calls
wglGetProcAddress, which works for OpenGL 1.1+ functions. Next, it determines ifpis null, meaning that this function call was not successful. Then it attempts to callGetProcAddress, working for GL1.1 functions.Then, it's simply a matter of calling
gladLoadGLLoader((GLADloadproc)GetAnyGLFuncAddress)).In practice, it is not neccessary to implement such a function yourself. GLAD has the inbuilt function,
gladLoadGL, which if you look at the code, callsgladLoadGLLoaderfor the internalget_procfunction. The code in this function does exactly what we've implemented (removing the#if/#endifs for other OSes):It tries to load the OpenGL function via
wglGetProcAddress, and then if that fails, usesGetProcAddress. Therefore, you can just callgladLoadGL.The wiki page Load OpenGL Functions has a lot of info on this.