I'm using Visual Studio 2013, and as I am learning OpenGL 3.3 I thought best to use
#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
to force 'intellisense' to not even show old depreciated functions such as glVertex2f etc...
However the inclusion of said #define prevents any gl* functions from showing up. Even glViewport is undefined. When attempting to compile a simple application I get among many errors
error C3861: 'glViewport': identifier not found
glcorearb.h is my include files path though, downloaded from http://www.opengl.org/registry/api/GL/glcorearb.h only yesterday.
I might be doing something completely wrong here. But here is my full source code...
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#define GLFW_INCLUDE_GLCOREARB
// Include GLFW3
#include <GLFW/glfw3.h>
//Error Callback - Outputs to STDERR
static void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
//Key Press Callback
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main(){
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
// Initialise GLFW
if (!glfwInit())
{
fputs("Failed to initialize GLFW\n", stderr);
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 2); // 2x antialiasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
// Open a window and create its OpenGL context
window = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float)height;
glViewport(0, 0, width, height);
glClearColor(0.5f, 0.7f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
Related
When I started I used the GLFW example code:
#include <GLFW/glfw3.h>
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
When running this it gives me a black screen titled "Hello world" which is exactly what I want. But by simply adding GLAD:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
...and giving window hints:
//Specify the OpenGL versions we're using
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Suddenly it tells me the window failed to initialize.
But by simply adding this:
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
...it allows the window to initialize but crashes when glClear(GL_COLOR_BUFFER_BIT) is called and it gives me the error
'./Voxel\ Game' terminated by signal SIGSEGV (Address boundary error)
I know this because when I remove that line it works, it just doesn't clear the screen.
This is the full code I have now in case the error is somewhere else in there:
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define SCREEN_WIDTH 640
#define SCREEN_HIEGHT 480
int main()
{
GLFWwindow* window;
//Initialize the library
if (!glfwInit())
{
std::cout << "Failed to initalize GLFW" << std::endl;
return -1;
}
//Specify the OpenGL versions we're using
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
//Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HIEGHT, "Voxel Game", NULL, NULL);
if (!window)
{
std::cout << "Failed create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
//Make the window's context current
glfwMakeContextCurrent(window);
//Loop until the user closes the window
while (!glfwWindowShouldClose(window))
{
//Render here
//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//Swap front and back buffers
glfwSwapBuffers(window);
//Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
You are not initializing glad, add gladLoadGL(glfwGetProcAddress); after glfwMakeContextCurrent() and check it returns OK.
In general, there is no OpenGL library apart from some old OpenGL1.1 stuff (in Windows at least), all those GL calls are implemented in the graphics drivers directly, GLAD library just defines a lot of function pointers and wraps them in nicer macros. Then during initialization, it will dynamically load the functions from the drivers present on the machine. Hence the need to generate GLAD for specific OpenGL version.
So if you get segfaults on some GL calls, a good guess is some of those functions were not found, maybe because they are not supported on the HW or because you did not setup GLAD/GLFW correctly.
It seems that I am having a seg fault while using GLFW and OpenGL on ArchLinux, DWM (fully updated and patched).
I retraced the code and it is having the segFault in the glfwSwapBuffers(window).
Here is my code :
main.cpp
#include <iostream>
#include "gui/window.h"
int main(int, char**) {
Window window("Test GL", 800, 600);
if(!window.hasCorrectlyLoaded()) {
return 1;
}
while (!window.shouldClose())
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
window.pollEvents();
}
}
window.h
#ifndef __WINDOW_H__
#define __WINDOW_H__
#include <string>
#include <glad/gl.h>
#include <GLFW/glfw3.h>
class Window {
private:
GLFWwindow *window;
bool correctlyLoaded;
public:
Window(const std::string&, int, int);
~Window();
const bool hasCorrectlyLoaded();
const bool shouldClose();
const void pollEvents();
};
#endif // __WINDOW_H__
window.cpp
#include "window.h"
#include <spdlog/spdlog.h>
Window::Window(const std::string& title, int width, int height)
{
correctlyLoaded = false;
if(!glfwInit()) {
spdlog::default_logger()->critical("Could not load GLFW");
return;
}
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, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (!window)
{
spdlog::default_logger()->critical("Failed to create GLFW window !");
return;
}
glfwMakeContextCurrent(window);
if (!gladLoadGL(glfwGetProcAddress))
{
spdlog::default_logger()->critical("Failed to load OpenGL !");
return;
}
spdlog::default_logger()->info("Loaded OpenGL {}", glfwGetVersionString());
glViewport(0, 0, width, height);
correctlyLoaded = true;
}
const void Window::pollEvents()
{
glfwSwapBuffers(window);
glfwPollEvents(); //<- Seg fault here
}
Window::~Window()
{
glfwTerminate();
}
const bool Window::hasCorrectlyLoaded()
{
return correctlyLoaded;
}
const bool Window::shouldClose()
{
return glfwWindowShouldClose(window);
}
While further researching, I stumbled upon an answer that told me to set the glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API) window hint but I still got a segfault, but at a different place :
GLFW source code
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT,
"Cannot swap buffers of a window that has no OpenGL or OpenGL ES context"); //<- Seg fault without window hint
return;
}
window->context.swapBuffers(window); //<- Seg fault with window hint
}
Here is the output I get from the logging :
[2022-05-24 20:01:04.252] [info] Loaded OpenGL 3.4.0 X11 GLX Null EGL OSMesa monotonic
[1] 432406 segmentation fault (core dumped) /home/lygaen/code/testgl/build/testgl
Your problem occurs in Window.cpp, at this line:
//...
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); //<---
if (!window)
{
//...
You've redeclared window as a local variable to this constructor, and as a result, the pointer never escapes the constructor, and is dangled.
A good habit when trying to assign class members is to use the this keyword. It is often redundant, but it does help indicate intent. So the code should be changed to this:
//...
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
this->window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); //<---
if (!this->window)
{
//...
If your style guidelines don't permit it, you can omit the this->; the only important part is that you're not declaring an entirely new variable that's shadowing the class member.
When I attempt to generate a buffer by executing the glGenBuffer() function - no function like that is found.
Some functions are still working, and from what I see most do work, for instance the following code works perfectly:
#include <iostream>
#include <GLFW/glfw3.h>
using namespace std;
class Window_Manager
{
public:
GLFWwindow* window;
int Create_Window(int width, int height, const char* title) {
if (!glfwInit()) {
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_FOCUSED, GL_TRUE);
window = glfwCreateWindow(width, height, title, NULL, NULL);
if (window == NULL) {
cout << "Failed to create a window! Aborting early..." << endl;
Terminate_Window(window);
return -1;
}
glfwMakeContextCurrent(window);
glViewport(0, 0, width, height);
return 1;
}
void Terminate_Window(GLFWwindow* window) {
glfwSetWindowShouldClose(window, GL_TRUE);
glfwTerminate();
}
};
but this code does not:
#include <GLFW/glfw3.h>
#include <Engine_Manager.h>
#include <iostream>
using namespace std;
class Shape2D
{
int VBO;
int Setting_Up(){
VBO = glGenBuffer();
return 1;
}
};
In addition to replacing glGenBuffer with glGenBuffers(1, &VBO) as rpress mentioned in the comments, OpenGL is a weird library in that you have to load most of the functions dynamically.
The exact details differ from platform to platform. On Windows, for example, you can use wglGetProcAddress to get pointers to desired functions.
Rather than do it manually, GLEW is an excellent library for getting OpenGL function pointers easily. Other options are documented on the OpenGL wiki.
I have created a simple OpenGL program, following the LearnOpenGL tutorial. It just creates a window and fills it with a color. I am using Visual Studio 2019.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
int main() {
// Initialize GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create GLFW Window
GLFWwindow* window = glfwCreateWindow(800, 600, "Golden Retriever", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// Render Loop
while (!glfwWindowShouldClose(window)) {
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
The program works perfectly, however it uses way too much CPU (around 50%). Is it something in Visual Studio properties, or am i just doing something wrong in my code?
You can enable vsync with glfwSwapInterval(1)
The way Windows measures CPU time falls flat on its face for processes that spend most of their time blocking (=waiting) on kernel calls. What happens in your case is, that in order to V-Sync your program has to wait for the vertical retrace to happen. That usually involves waiting for a synchronization object that's locked from kernel context.d
In order to make Windows measure consumed CPU time accurately add a Sleep(1) right before the buffer swap call.
I use MinGW compiler and Code::Blocks IDE, 16.01.
I have interested in graphic library OpenGL. I've started to find articles and found one.
I've set up glew, freeglut and glfw by myself without using cMaker. Then, I've decided to link libraries into the project. So, I have the following sequence in Linker settings:
C:\MinGW\lib\glew\glew32s.lib
C:\MinGW\lib\freeglut\libfreeglut.a
C:\MinGW\lib\freeglut\libfreeglut_static.a
C:\MinGW\lib\glfw\libglfw3dll.a
C:\MinGW\lib\glfw\libglfw3.a
Following by this tutorial (in russian language) I've written in linker settings glew32s.lib (with 's'), 'cause it's a static library and I need this one. After that I've tried to compile but get these errors:
C:\MinGW\lib\glew\glew32s.lib(tmp\glew_static\Release\Win32\glew.obj):(.text$mn+0x7)||undefined reference to `_imp__wglGetProcAddress#4'|
C:\MinGW\lib\glew\glew32s.lib(tmp\glew_static\Release\Win32\glew.obj):(.text$mn+0x4)||undefined reference to `_imp__wglGetProcAddress#4'|
The code I've tried to compile is:
#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;
// The MAIN function, from here we start the application and run the game loop
int main()
{
std::cout << "Starting GLFW context, OpenGL 3.3" << std::endl;
// Init GLFW
glfwInit();
// Set all the required options for GLFW
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);
// Create a GLFWwindow object that we can use for GLFW's functions
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
glewExperimental = GL_TRUE;
// Initialize GLEW to setup the OpenGL Function pointers
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
// Define the viewport dimensions
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Game loop
while (!glfwWindowShouldClose(window))
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
}
// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
std::cout << key << std::endl;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
Then I wrote in linker settings glew32.lib (without 's'), comment glewExperimental = GL_TRUE; line and try again.
The program was compiled successfully. It was run and the result was as it must be.
But I want to use a static library instead of dynamic. How can it be solved?
I guess that library 'glew32s.lib' is built with Visual studio. So you cannot link with it unless you change your compiler.
I suggest you get a GLEW library built with MinGW or build one by yourself. Libraries for MinGW are named 'libNAME.a',
Also, dynamic libraries have no limitation on its name, so there could be no difference between static library (instead, they are named, like, libNAME_static.a or libNAMEs.a, ...)