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.
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 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.
I'm trying to my desktop image capture. (All images, including the desktop output to the monitor)
It's easy using window API (BitBlt or CImageClass) and it's not the way I want.
I want do it using opengl. so I found glReadPixel funtion and window TRANSPARENT.
But it just read pixel own Windows application screen.(Save as bmp file and check)
Initialize()
glfwSetErrorCallback(errorCallback);
if (!glfwInit()) {
std::cerr << "Error: GLFW " << std::endl;
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_DEPTH_BITS, 16);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
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_SAMPLES, 4);
const int Monitor_count = GetMonitors();
GLwindow = glfwCreateWindow(
nWidth, // width
nHeight, // height
"OpenGL_Test", // window title
NULL, NULL);
if (!GLwindow) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSwapInterval(1);
if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
//...
}
glfwSetWindowOpacity(GLwindow, 0.0f);
auto Mode = glfwGetVideoMode(Monitor[0]);
glfwMakeContextCurrent(GLwindow);
glfwSetKeyCallback(GLwindow, keyCallback);
glewExperimental = GL_TRUE;
GLenum errorCode = glewInit();
if (GLEW_OK != errorCode) {
std::cerr << "Error: GLEW - " << glewGetErrorString(errorCode) << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
if (!GLEW_VERSION_3_3) {
std::cerr << "OpenGL 3.3 API is not available." << std::endl;
glfwTerminate();
exit(EXIT_FAILURE);
}
glViewport(0, 0, nWidth, nHeight);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "Error: " << std::endl;
}
return true;
Roop
while (!glfwWindowShouldClose(GLwindow)) {
Sleep(10);
glClearColor(0.0f, 0.3f, 0.3f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
unsigned char *image = (unsigned char*)malloc(sizeof(unsigned char)*nWidth*nHeight * 3);
glReadPixels(0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, image);
glfwPollEvents();
}
return true;
Q1. Is it possible desktop capture(Full Image GPU output) with OPENGL?
Q2. If Q1 is possible, Should I use FBO and PBO GL_BACK??
Q3. How to access to mother window or GPU adapter? >> GL seems to strongly reject this.(I don't want any rendering, just read pixel data from GPU(Desktop image. not rendered by my application.)(If it is possible ...))
Anybody shows to me about link or idea?
What you're asking for is something completely outside the scope of OpenGL. OpenGL is designed to be a platform-agnostic API for applications to talk about drawing stuff into framebuffers in an abstract fashion. OpenGL has no notion of windows*, screens, or a desktop. OpenGL doesn't operate at a level where such concepts exist. Heck, OpenGL doesn't even know what a GPU is. OpenGL is supposed to be initialized through platform-specific mechanisms to establish a context which assigns actual meaning to OpenGL API calls. As far as I know, there is no way to set up an OpenGL context with a framebuffer whose contents would somehow correspond to the desktop on Windows (or any other platform I'm aware of). As far as my understanding goes, this wouldn't really make sense…
To do what you want to do, you'll have to rely on the respective platform-specific APIs. The probably simplest way on Windows is to get an HDC for the entire desktop and BitBlt from there. See, e.g., this question for more on that. A more modern approach would be to use the DXGI Desktop Duplication API.
(*) yes, I know the OpenGL specification technically does talk about "windows" in a few places; but it only really does so when it's talking about all the things it's not responsible for…
I'm trying to my desktop image capture. (All images, including the desktop output to the monitor)
It's easy using window API (BitBlt or CImageClass) and it's not the way I want.
But it's the way it's supposed to be done.
I want do it using opengl. so I found glReadPixel funtion
You can't. OpenGL doesn't "know" about the desktop, or other windows (or actually what windows are at all). The function glReadPixels will work reliably only for images that have been drawn with OpenGL itself.
You can't use OpenGL to take screenshots! On older computers it might seem to work, but that's only because of their older memory management where when you create a new window, its memory will be "cut" from what was below and if you read that, it looks like a way to make screenshots. But it is not.
I have a small problem with glfw.
My code is really simple, I juste want to create an empty window.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main(void) {
// initialise the windows
GLFWwindow *window;
if (!glfwInit()) {
return -1;
}
// create a windows
window = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!window) {
fprintf(stderr, "Failed to initialize GLFW\n");
glfwTerminate();
return -1;
}
// make the window's current context
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// loop until the window close
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// swap back and front buffers
glfwSwapBuffers(window);
// poll the events
glfwPollEvents();
}
std::cout << "finished ";
glfwTerminate();
return 0;
}
This code compile but when I run it, I only have a white window. The title of the window is correct but everything inside is white...
I try to use glClearColor like that
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1, 1, 0, 0);
but my window still white....
I use visual studio 2015.
How to get a black window ?
Edit :
I forgot to add this:
glfwMakeContextCurrent(window);
For future visitors I'm posting the edit as a formal answer.
The thing missing here is to set the newly created window as the current OpenGL context by calling glfwMakeContextCurrent(window);
Interestingly the comments in the code say you are doing this
// make the window's current context
But then you do not call the method above but instead set the background colour immediately after. If you add the above method call after this comment and before you set the background colour then when I run your code it works fine.
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").