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?
Why am I getting this error?
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.
How do I fix it?
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.
Related
I'm trying to change the background color in a window generated by OpenGL/GLFW and I'm using a similar code than the one in the GLFW docs. I'm on Ubuntu 20.04 and the window background is always black, no matter the parameters in the glClearColor() function.
I tried this on Windows 10 using VS and it worked perfectly, but on Ubuntu it's not working at all. No error messages are generated.
I also followed The Cherno's Sparky game engine series, and tried encapsulating the glClear() function in a class method, but this didn't change anything.
This is the whole code:
#include <iostream>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
int main(int argc, char *argv[])
{
std::cout << "Hello world!" << std::endl;
if (!glfwInit())
{
// Initialization failed
exit(EXIT_FAILURE);
}
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
if (!window)
{
// Window or OpenGL context creation failed
std::cout << "Error creating window!" << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
while (!glfwWindowShouldClose(window))
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
I'm supposed to get a window with a red background but it's black.
As additional elements, I'm also using CMake to help configuring and building the project (quite overkill I know), and I believe clang is the compiler used for the project. Maybe that influences the result.
You need an appropriate loader after glfwMakeContextCurrent(window).
If you are using glad, you should call gladLoadGL(glfwGetProcAddress) after glfwMakeContextCurrent(window) as the official doc suggests here.
I'm trying to run my first opengl program in C++, which opens a window, sets a background color, and gives a title, from Terminal on Mac OS X.
The code compiles and links fine. When I run the program the window and title open fine but the background color is always black.
It is my understanding that the function glClearColor sets the background color. However, no matter what parameters I pass to the function, the background color of the window is always black.
If anyone can explain to me what errors I'm making, I would very much appreciate it. Thanks and below is the code:
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const GLint WIDTH = 800, HEIGHT = 600;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if(nullptr == window)
{
std::cout << "Failed to create GLFW window" << '\n';
glfwTerminate();
return -1;
}
glewExperimental = GL_TRUE;
GLenum err=glewInit();
if(err != glewInit())
{
std::cout << "Failed to initialize GLEW" << '\n';
return -1;
}
glViewport(0, 0, screenWidth, screenHeight);
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.2f, 0.9f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
glClearColor, like all OpenGL functions, works on the current OpenGL context.
You're not setting your window's context as current for your calling thread, so your call to glClearColor does nothing here. Add:
glfwMakeContextCurrent(window);
before your loop.
From glfwMakeContextCurrent docs:
This function makes the OpenGL or OpenGL ES context of the specified window current on the calling thread. A context can only be made current on a single thread at a time and each thread can have only a single current context at a time.
For those of you crazy enough to use pure WIN32 programming:
If your PIXELFORMATDESCRIPTOR has the flag:
PFD_DOUBLEBUFFER
Then all draw calls target the back buffer.
You need to use the windows GDI32 call "SwapBuffers( HDC )" to show the results of your OpenGL calls.
wlgMakeCurrent()
glClearColor( R, G, B, 1.0 ); //: <--Make sure alpha isn't transparent.
glClear( GL_COLOR_BUFFER_BIT )
SwapBuffers( your_window_HDC ); //: from GDI32.dll
To get access to SwapBuffers I use LoadLibrary and GetProcAddress and
put the function pointer in my Win32 functions library.
Also notworthy:
Call SwapBuffers on the same thread as your OpenGL calls.
One more thing. I used multiple threads. So this might be helpful to know:
My window was created in thread "B"
My Context was created in thread "A" using HDC from thread "B"
My openGL draw calls are in thread "A".
I mention this because before I found out about SwapBuffers I thought the problem was because of my multi threading. OpenGL wasn't giving me any errors though, so I had to guess around and experiment and read.
I am trying to create a Blank Window in OpenGL with help of GLFW. below is my code
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <glfw3.h>
GLFWwindow* window;
#include <glm/glm.hpp>
using namespace glm;
int main( void )
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
window = glfwCreateWindow(800,600,"learnopengl",NULL,NULL);
if (window == NULL)
{
fprintf(stderr,"there is a problem with window creation\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
fprintf(stderr,"Failed to initialize GLEW\n");
return -1;
}
int width, height;
glfwGetFramebufferSize(window,&width,&height);
glViewport(0,0,width,height);
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
}
but when i try to run the above code instead of a black blank it shows an instance of my current screen in newly created window.
Why do you expect this code to result in a blank window?
As per the spec, the back buffer contents become undefined after you swap the buffers (and initially, they are of course undefined too). As a result, the output you should get is also undefined and basically anything might show up.
Add a glClear(GL_COLOR_BUFFER_BIT) to your render loop if you want some defined output.
I know the answer is late but may concern other people and help them, I ran this code and it's working pretty well, but the problem is not in your code, it is your video card driver, so what is happening ?
OpenGL has what is called "The Default Framebuffer", it is the Framebuffer (the buffer contains what you will see) that OpenGL is created with. It is created along with the OpenGL Context. Like Framebuffer Objects, the default framebuffer is a series of images. Unlike FBOs, one of these images usually represents what you actually see on some part of your screen. in other words the default framebuffer is the buffer used by the operating system to render your desktop and other application's windows, so your application is using the default framebuffer as the framebuffer is not edited by your app, so you may need to clear the framebuffer with some other values, let's say colors. this is your code edited with buffer clearing using colors.
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <glfw3.h>
GLFWwindow* window;
#include <glm/glm.hpp>
using namespace glm;
int main( void )
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
window = glfwCreateWindow(800,600,"learnopengl",NULL,NULL);
if (window == NULL)
{
fprintf(stderr,"there is a problem with window creation\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
fprintf(stderr,"Failed to initialize GLEW\n");
return -1;
}
int width, height;
glfwGetFramebufferSize(window,&width,&height);
glViewport(0,0,width,height);
//this is an added line
glClearColor(1, 1, 1, 1); //the RGBA color we will clear with
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
//this is an added line
glClear(GL_COLOR_BUFFER_BIT); //the buffer used to clear with
glfwSwapBuffers(window);
}
glfwTerminate();
}
Hope this answer and this code help other people who may have this situation.
for further information about the framebuffer check this link : https://learnopengl.com/Advanced-OpenGL/Framebuffers
EDIT: If anyone has this kind of error, and is using GLEW, when using OpenGL 4.5 functions, the following will help:
glewExperimental = GL_TRUE;
after that just initialize GLEW and you'll be fine.
I´m just starting out with OpenGL. Currently I am trying to clear the whole screen with red, as seen in this code here:
#include "GLFW/glfw3.h"
#define WIDTH 1280
#define HEIGHT 720
int main(void)
{
GLFWwindow *window;
if(!glfwInit()) {
return -1;
}
window = glfwCreateWindow(WIDTH, HEIGHT, "Test OpenGL", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
static GLfloat red[] = {1.0f, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 0, red);
while(!glfwWindowShouldClose(window)) {
//glEnableClientState(GL_VERTEX_ARRAY);
//glDisableClientState(GL_VERTEX_ARRAY);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
But there is a problem. I am using g++ to compile the code written in Code::Blocks. Also, I am learning with the OpenGL SuperBible 7th edition, where I got the code for clearing the screen with red. Before I was using glClearColor(255, 0, 0, 0) and then glClear(GL_COLOR_BUFFER_BIT);
But in this book the screen is cleared with glClearBufferfv, which throws the following exception:
error: 'glClearBufferfv' was not declared in this scope
Of course I want to use the code in the book for learning purposes, so it would be great, if that would work. Sadly, it doesn´t. Any idea, why?
glClearBufferfv is a newer OpenGL function, which means it is technically possible that a graphics card that speaks OpenGL doesn't support it. This means that the function needs to be loaded, either by you or by an OpenGL loading library, before you can use it.
The SuperBible example code comes with the gl3w loader as part of its s7 helper library. You could either:
use s7, which the other examples in the book will likely depend on as well
skip s7 and use gl3w or any other loader, like my personal favourite libepoxy
don't use a loader and load the functions you need by hand. This gets tedious very quick, but it does mean you get to see what's going on.
The GLFW documentation has some useful pointers as well.
I've created a very simple implementation of a GLFW window. My implementation looks like so
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include glfw for window handling
#include <GLFW/glfw3.h>
int SCREEN_WIDTH = 1280;
int SCREEN_HEIGHT = 720;
GLFWwindow* window;
int main() {
if(!glfwInit()) {
fprintf( stderr, "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_COMPAT_PROFILE);
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Title", NULL, NULL);
if( !window )
{
fprintf( stderr, "Failed to create window!\n" );
glfwTerminate();
return -1;
}
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
do {
glfwSwapBuffers(window);
} while(!glfwGetKey(window, GLFW_KEY_ESCAPE));
glfwTerminate();
return 0;
}
It compiles fine, but when I run the application it just "freezes", not showing the correct clear color or anything. It just thinks like crazy (that "thinking"-cursor icon in Windows 7 spins and never stops).
I'm wondering why it freezes like such, does anyone have an idea?
EDIT:
Found the solution to my problem. I was learning from a GLFW2 example, but having the newest version (GLFW3) required me to redo the code some; the thing I didn't realize was that the glSwapBuffers(window) call doens't call glfwPollEvents() by itself, giving me the problem I had.
You're not clearing the buffers, hence the clear colour is not showing through.
You're not adding any kind of delay, so you're swapping empty buffers flat out ("thinking like crazy").