1

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.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
LucasSokol
  • 125
  • 4
  • Did you create a WGL context first? May you show your code for further debugging? You should consider reading [Creating an OpenGL Context](https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_%28WGL%29). – new Q Open Wid Jul 07 '23 at 16:51
  • Yes. First I created an OpenGL context successfuly using wglCreateContextAttribsARB . Then make it current using wglMakeCurrent function. And made the versions of the OpenGL compatible. And also checked every step if there was an error. I don't think the issue is related to the OpenGL context. – LucasSokol Jul 07 '23 at 17:30
  • https://stackoverflow.com/a/58054254/3871028 – Ripi2 Jul 07 '23 at 18:24
  • would [this](https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions) and specifically the `GetAnyGlFuncAddress`, be interesting to you? – new Q Open Wid Jul 07 '23 at 20:00
  • 1
    YEESSS! That was it. I've been dealing with that stuff since the morning. Checked my OpenGL context creation function like 20 times. Thank you very much for your concern. Updating my quesiton rn. – LucasSokol Jul 07 '23 at 20:43

1 Answers1

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." Indeed, wglGetProcAddress does 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 why glGetString is 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.dll itself. Therefore, you can use the Windows function GetProcAddress on opengl32.dll for these functions. However GetProcAddress, of course, does not work on newer GL functions.

But we can create a new function to 'bridge the gap' between these two:

void *GetAnyGLFuncAddress(const char *name)
{
  void *p = (void *)wglGetProcAddress(name); // load newer functions via wglGetProcAddress
  if(p == 0 ||
    (p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
    (p == (void*)-1) ) // does it return NULL - i.e. is the function not found?
  {
    // could be an OpenGL 1.1 function
    HMODULE module = LoadLibraryA("opengl32.dll"); 
    p = (void *)GetProcAddress(module, name); // then import directly from GL lib
  }

  return p;
}

This function, as you can see, first calls wglGetProcAddress, which works for OpenGL 1.1+ functions. Next, it determines if p is null, meaning that this function call was not successful. Then it attempts to call GetProcAddress, 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, calls gladLoadGLLoader for the internal get_proc function. The code in this function does exactly what we've implemented (removing the #if/#endifs for other OSes):

void* get_proc(const char *namez) {
    void* result = NULL;
    if(libGL == NULL) return NULL;
    if(gladGetProcAddressPtr != NULL) {
        result = gladGetProcAddressPtr(namez); // essentially wglGetProcAddress - see glad's internal open_gl()
    }
    if(result == NULL) {
        result = (void*)GetProcAddress((HMODULE) libGL, namez);
    }
    return result;
}

It tries to load the OpenGL function via wglGetProcAddress, and then if that fails, uses GetProcAddress. Therefore, you can just call gladLoadGL.


The wiki page Load OpenGL Functions has a lot of info on this.

new Q Open Wid
  • 2,225
  • 2
  • 18
  • 34