I have been trying to create an OpenGL window making use of GLAD and GLFW, following the instructions found at learnopengl.com and glfw.org. At first glance according to the documentation, this is enough to get a window working:
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
using namespace std;
// framebuffer size callback function
void resize(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void render(GLFWwindow* window) {
// here we put our rendering code
}
void main() {
int width = 800;
int height = 600;
// We initialzie GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Now that it is initialized, we create a window
GLFWwindow* window = glfwCreateWindow(width, height, "My Title", NULL, NULL);
// We can set a function to recieve framebuffer size callbacks, but it is optional
glfwSetFramebufferSizeCallback(window, resize);
//here we run our window, swapping buffers and all.
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.1f, 0.0f);
render(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
Assumming your Visual Studio enviroment is configured correctly, this should run without issues. However, if we run the project, this error appears:
Exception thrown at 0x0000000000000000 in CPP_Test.exe: 0xC0000005: Access violation executing location
We did not have any errors showing up before running the program, why is this showing up?
From learnopengl.com
Because OpenGL is only really a standard/specification it is up to the driver manufacturer to implement the specification to a driver that the specific graphics card supports. Since there are many different versions of OpenGL drivers, the location of most of its functions is not known at compile-time and needs to be queried at run-time. It is then the task of the developer to retrieve the location of the functions he/she needs and store them in function pointers for later use.
GLAD is a library that defines all the functions needed to work with OpenGL without having to work out how ourselves.
When we call a GLAD function, glClear
, for example, we are actually calling a function called glad_glClear
from the gl context. When this call is made, GLAD looks for the current gl context in order to affect the correct window, sort of speak. The reason this problem appears is because GLAD will always make use of a context, even if it doesn't find one.
When this happens, a call at this location in memory (0x0000000000000000
) is made, and since it is not a GL context (it's just a NULL pointer), an Access violation
exception is thrown.
Fixing this problem is quite simple. If you are reading this, you probably are using GLAD and GLFW. GLFW has a function that allows us to define the context in just one call after the creation of the window:
glfwMakeContextCurrent(GLFWwindow* window);
Great, now we have set our context, but GLAD doesn't know yet. To do that, we just initialize GLAD using gladLoadGL
right after setting the context.
We can now run our program again, and everything should work just fine.
Here is the complete code with this little change:
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
using namespace std;
// framebuffer size callback function
void resize(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void render(GLFWwindow* window) {
// here we put our rendering code
}
void main() {
int width = 800;
int height = 600;
// We initialzie GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Now that it is initialized, we create a window
GLFWwindow* window = glfwCreateWindow(width, height, "My Title", NULL, NULL);
// We set the context to be our window and then initialize GLAD
glfwMakeContextCurrent(window);
gladLoadGL();
// We can set a function to recieve framebuffer size callbacks, but it is optional
glfwSetFramebufferSizeCallback(window, resize);
//here we run our window, swapping buffers and all.
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.1f, 0.0f);
render(window);
glfwSwapBuffers(window);
glfwPollEvents();
}
}
I myself struggled for hours to find this solution, because everyone solved it initializing GLEW, but it is not included in this project, so that didn't work for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With