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.
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'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've been trying to incorporate shaders and OpenGl into a wxWidgets program. I've used the links below:
http://nehe.gamedev.net/article/glsl_an_introduction/25007/
http://www.lighthouse3d.com/tutorials/glsl-tutorial/hello-world-in-glsl/
Now I've been trying in a test program to use the shaders provided by the lighthouse3d tutorial and recreate the output, (a blue teapot spinning slowly on a white background). I can't seem to get anything to draw though and all I can see is a black screen. My code so far is below, (I'm going to ignore most of the shaders intially as I'm 99% sure they're fine):
void BasicGLPane::render( wxPaintEvent& evt )
{
//wxGLCanvas::SetCurrent(*m_context);
wxPaintDC(this);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//prepare2DViewport(0,0,getWidth()/2, getHeight());
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
//glRotatef(a,0,1,1);
glutSolidTeapot(1);
glFlush();
//a+=0.1;
SwapBuffers();
}
void BasicGLPane::InitializeGLEW()
{
//prepare2DViewport(0,0,getWidth(), getHeight());
// The current canvas has to be set before GLEW can be initialized.
wxGLCanvas::SetCurrent(*m_context);
GLenum err = glewInit();
// If Glew doesn't initialize correctly.
if(GLEW_OK != err)
{
std::cerr << "Error:" << glewGetString(err) << std::endl;
const GLubyte* String = glewGetErrorString(err);
wxMessageBox("GLEW is not initialized");
}
BasicGLPane::BasicGLPane(wxFrame* parent, int* args) :
wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{
m_context = new wxGLContext(this);
// To avoid flashing on MSW
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}
I've had thoughts as to why I'm not getting any output. One thought I'm having is something to do with the m_context. I'm having to set the current context for WxWidgets before I can run GLEW. There's also a number of properties that in the tutorial are initialized and I'm not using these functions in my wxWidgets version and I'm wondering if I should. These are:
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("MM 2004-05");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
glEnable(GL_CULL_FACE);
But I'm quite keen to avoid using glut and have managed to avoid it up until now. The only reason I've previously added it is to try and replicate the tutorial's behaviour.
Edit:
I'm going to add a bit more as I have noticed one or two bits of odd behaviour. If I call this function in my draw:
void BasicGLPane::prepare2DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Black Background
glEnable(GL_TEXTURE_2D); // textures
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glViewport(topleft_x, topleft_y, bottomrigth_x-topleft_x, bottomrigth_y-topleft_y);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(topleft_x, bottomrigth_x, bottomrigth_y, topleft_y);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
I can get the background to change colour when I change the window size. I should also mention, it's NOT refreshing every frame, It only draws one frame and then won't call the render function again until I change the window size.
Your code looks good so far. One thing you find in a lot of tutorials, but is bad practice is, that there's apparently some initialization happening. This is not the case. OpenGL is not initialized, it's a state machine and you're supposed to set state when you need it. The lines
glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
glEnable(GL_CULL_FACE);
Are perfectly happy in the drawing function. You also need to setup a projection. In tutorials you often find them to be set in the window resize handler. Please don't fall into this bad habit. Projection and viewport are drawing state, so set them in the drawing function.
If you're using OpenGL-3 (core profile) or later you must supply at least a vertex and a fragment shader. In the older versions each shader stage is optional and there are builtin variables to provide a common grounds for communication between fixed function and programmable pipeline. However I strongly advise against mixed operation. Always use shaders and use both a vertex and a fragment shader. In the long term they make things soooo much easier.
Turns out I didn't need the gluLookAt in my render.