I have the following function:
void introMenu(unsigned int texture,Shader shader, unsigned int VAO){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
shader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
I call it after the following function:
int buildWindow(GLint WINDOW_WIDTH,GLint WINDOW_HEIGHT,char *windowTitle,GLint focused, bool fullscreen){
if(window!=NULL){
glfwDestroyWindow(window);
}
glfwWindowHint(GLFW_RESIZABLE,GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE,GLFW_TRUE);
glfwWindowHint(GLFW_DECORATED,GLFW_TRUE);
glfwWindowHint(GLFW_FOCUSED,GLFW_TRUE);
glfwWindowHint(GLFW_FLOATING,focused);
glfwWindowHint(GLFW_MAXIMIZED,GLFW_FALSE);
glfwWindowHint(GLFW_CENTER_CURSOR,GLFW_FALSE);
glfwWindowHint(GLFW_SCALE_TO_MONITOR,GLFW_TRUE);
glfwWindowHint(GLFW_SAMPLES,4);
glfwWindowHint(GLFW_DOUBLEBUFFER,GLFW_TRUE);
glfwWindowHint(GLFW_REFRESH_RATE,GLFW_DONT_CARE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
if(!fullscreen){
window=glfwCreateWindow(WINDOW_WIDTH,WINDOW_HEIGHT,windowTitle,NULL,NULL);
}
else{
window=glfwCreateWindow(WINDOW_WIDTH,WINDOW_HEIGHT,windowTitle,glfwGetPrimaryMonitor(),NULL);
}
if(window==NULL){
fprintf(stderr,"Failed to open GLFW window, possibly because of your Intel GPU\n");
getchar();
glfwTerminate();
return -1;
}
//get monitor size
const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
int monitorX, monitorY;
glfwGetMonitorPos(glfwGetPrimaryMonitor(), &monitorX, &monitorY);
//get window size
int windowWidth, windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
//center window
glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2);
//window icon
GLFWimage icon[1];
icon[0].pixels = stbi_load("images/icon/icon.png", &icon[0].width, &icon[0].height, 0, 4);
glfwSetWindowIcon(window, 1, icon);
stbi_image_free(icon[0].pixels);
//make window contest
glfwMakeContextCurrent(window);
return 0;
}
, which I use to resize the window and/or set its parameters. I start by destroying the current one and then, create a new one. When I call the first function after this one the following error occurs: OpenGL nvoglv32.dll error
If I don't call the buildWindow function, it works fine.
Why does it happen and how do I solve this issue?
In GLFW, the GL context is tied to the window, and when you destroy the window, you destroy the GL context - and all the GL objects with it: textures, buffers, shaders, VAOs, whatever. And all the GL object names your code still holds become invalid. If you re-create the window, you have to re-create all of your GL objects with it.
There is no easy way around that in GLFW. You can fiddle around with shared contexts - but even shared contexts only share the "heavy" state objects like textures and buffers, but not the "light-weight" state containers like VAOs.
Note that the underlying GL binding APIs (wgl, glX, egl, ...) do not have such restrictions - windows and GL contexts are distinct entities there, and destroying the window will not affect the GL context, you can later bind it to another window, but you have to make sure that the window is comaptible to the context (with varying rules depending on the platform you work on).
Related
This is my first big OpenGL project and am confused about a new feature I want to implement.
I am working on a game engine. In my engine I have two classes: Renderer and CustomWindow. GLFW needs to be initialized, then an OpenGL context needs to be created, then glew can be initialized. There is no problem with this, until I decided to support multiple windows to be created at the same time. Here are the things I am confused about:
Do I need to initialize GLEW for every window that is created? If no, can I still call glewInit() for every window creation and everything be fine?
If I create a window, and then destroy it, do I have to call glewInit() again and will I have to call these functions again?:
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numberOfTexturesSupported);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
If there is any off topic comments that would help, they are very welcomed.
Update 1: More Context
For reference, the reason I want to do this is to implement multiple window rendering that share the same OpenGL context. Note, each window uses its own vertex array object (VAO). Here is the code for reference:
// CustomWindow.cpp
CustomWindow::CustomWindow() {
window = nullptr;
title = defaultTitle;
shouldClose = false;
error = false;
vertexArrayObjectID = 0;
frameRate = defaultFrameRate;
window = glfwCreateWindow(defaultWidth, defaultHeight, title.c_str(), nullptr, nullptr);
if (!window) {
error = true;
return;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
error = true;
return;
}
glGenVertexArrays(1, &vertexArrayObjectID);
glBindVertexArray(vertexArrayObjectID);
allWindows.push_back(this);
}
CustomWindow::CustomWindow(int width, int height, const std::string& title, GLFWmonitor* monitor, GLFWwindow* share) {
window = nullptr;
this->title = title;
shouldClose = false;
error = false;
vertexArrayObjectID = 0;
frameRate = defaultFrameRate;
window = glfwCreateWindow(width, height, title.c_str(), monitor, share);
if (!window) {
error = true;
return;
}
glfwMakeContextCurrent(window);
glGenVertexArrays(1, &vertexArrayObjectID);
allWindows.push_back(this);
}
CustomWindow::~CustomWindow() {
if (window != nullptr || error)
glfwDestroyWindow(window);
unsigned int position = 0;
for (unsigned int i = 0; i < allWindows.size(); i++)
if (allWindows[i] == this) {
position = i;
break;
}
allWindows.erase(allWindows.begin() + position);
if (mainWindow == this)
mainWindow = nullptr;
}
// Rendere.cpp
Renderer::Renderer() {
error = false;
numberOfTexturesSupported = 0;
if (singleton != nullptr) {
error = true;
return;
}
singleton = this;
// Init GLFW
if (!glfwInit()) {
error = true;
return;
}
// Set window hints
glfwWindowHint(GLFW_MAXIMIZED, true);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_SAMPLES, 4);
// Init GLEW
if (glewInit() != GLEW_OK) {
error = true;
return;
}
// Set graphics message reporting
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(openglDebugCallback, nullptr);
// Set up OpenGL
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &numberOfTexturesSupported);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_MULTISAMPLE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_PROGRAM_POINT_SIZE);
}
After some research, i would say that it depends, therefore it's always best to have a look at the base to form an opinion.
The OpenGL wiki has some useful information to offer.
Loading OpenGL Functions is an important task for initializing OpenGL after creating an OpenGL context. You are strongly advised to use an OpenGL Loading Library instead of a manual process. However, if you want to know how it works manually, read on.
Windows
This function only works in the presence of a valid OpenGL context. Indeed, the function pointers it returns are themselves context-specific. The Windows documentation for this function states that the functions returned may work with another context, depending on the vendor of that context and that context's pixel format.
In practice, if two contexts come from the same vendor and refer to the same GPU, then the function pointers pulled from one context will work in the other.
Linux and X-Windows
This function can operate without an OpenGL context, though the functions it returns obviously can't. This means that functions are not associated with a context in any way.
If you take a look into the source code of glew (./src/glew.c), you will see that the lib simply calls the loading procedures of the underlying system and assigns the results of those calls to the global function pointers.
In other words, calling glewInit multiple times has no other side effect other than that explained in the OpenGL wiki.
Another question would be: do you really need multiple windows for that task? A different approach could be achieved with only one context and multiple framebuffer objects.
Multiple contexts (sharing resources between them) and event handling (which can only be called from the 'main' thread) needs proper synchronization and multiple context switches.
I am new to the ImGui library and recently i've been trying out the examples included. Everything worked like a charm until I changed the include (and functions) of gl3w to glad (the loader i would like to use). The moment I swapped between the two loaders I got a segmentation fault exception inside the imgui_impl_glfw_gl3.cpp file. I found a post which suggested that this may happen because of some functions failing to "bind" and producing nullpointers.
I have located the error in line 216 of imgui_impl_glfw_gl3.cpp
this is the code in line 216:
glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
I have also changed the include file in imgui_impl_glfw_gl3.cpp from gl3w to glad with no results.
This is the main function i am executing (it's the basic opengl3 example of imgui using glad):
#include "gui/imgui.h"
#include "gui/imgui_impl_glfw_gl3.h"
#include <stdio.h>
#include <glad/glad.h> // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you.
#include <GLFW/glfw3.h>
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error %d: %s\n", error, description);
}
int main(int, char**)
{
// Setup window
glfwSetErrorCallback(error_callback);
if (!glfwInit())
return 1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync
glfwInit();
// Setup ImGui binding
ImGui_ImplGlfwGL3_Init(window, true);
// Setup style
//ImGui::StyleColorsDark();
ImGui::StyleColorsClassic();
bool show_demo_window = true;
bool show_another_window = false;
bool algo = true;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
// Main loop
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
ImGui_ImplGlfwGL3_NewFrame();
// 1. Show a simple window.
// Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug".
{
static float f = 0.0f;
static int counter = 0;
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("COLORINES", (float*)&clear_color); // Edit 3 floats representing a color
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
ImGui::Checkbox("Booleanooooo", &algo);
ImGui::Checkbox("Another Window", &show_another_window);
if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("pues se ve que hay texto: %d", algo);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
}
{
ImGui::Begin("VENTANA WAPA");
ImGui::Text("POS SA QUEDAO BUENA VENTANA");
static float yee = 0.0f;
ImGui::SliderFloat("lel", &yee,1.0f,0.5f);
ImGui::End();
}
// 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window);
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
// 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui!
if (show_demo_window)
{
ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly!
ImGui::ShowDemoWindow(&show_demo_window);
}
// Rendering
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();
glfwSwapBuffers(window);
}
// Cleanup
//ImGui_ImplGlfwGL3_Shutdown();
glfwTerminate();
return 0;
}
I have no clue why this is happenning and I'm pretty new to openGL an ImGui so, any ideas? :(
Glad & gl3w are both extension loader libraries. They generally need to be initialized on a current GL context before use.
The original code called gl3wInit(). Yours is missing any sort of glad init.
Make sure you initialize glad (gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) after glfwMakeContextCurrent() and before you call any OpenGL functions.
Otherwise all the OpenGL function pointers glad declares will remain NULL. Trying to call NULL function pointers generally doesn't go well for a process.
I'm new to learning OpenGL in fact I just started following along a great resource called "learningopengl", This resources teaches how to setup GLFW and GLAD to use OpenGL on visual studio 2017. However, I've noticed when running even just an extremely basic program that only builds a blank window, that can be resized (following along the learning material) it takes visual studio consistently 40 or so seconds to actually load the program. it runs fine once its up, it simply takes an annoyingly long time to open.
I know this isn't supposed to take so long because through my searching around and looking at videos of people using these same libs/includes when they run there sample programs they load up instantly.
I was hoping I could find out why this is the case. for reference the sample code I'm running is show below.
#include <glad/glad.h>
#include <GLFW\glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main() {
// glfw: initialize and configure
// -----------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all openGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// render loop
// -----------
while (!glfwWindowShouldClose(window)) {
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc
// -----------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// glfw: terminate, clearing all perviously allocated glfw recourses
// -----------------------------------------------------------------
glfwTerminate();
return 0;
}
// glfw: whenever the window size is changed (by OS or user resize) this callback function executes
// ------------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger then specified on retina displays.
glViewport(0, 0, width, height);
}
Just a finial clarification, I do not mean that any kind of frame rate is slow, I mean from the time I tell visual studio to run the project (Ctrl+f5 or run the debugger) to the time I can see the actual OpenGL window i'm trying to make takes approximately 40 seconds or more.
Also when I run the code a cmd prompt runs behind it I was also wondering why that happens and if there is a way to prevent it or if it happens because of a setting.
I have a GLFW3 window that I am trying to change from resizable to not resizable.
I tried changing the Window Hint after the window was created but this doesn't do anything as the hints only affect window to be created.
what I tried:
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE)
Is this possible? One way of doing it that I thought of was having a onResize function that changes the window size back to the current size after being set not resizable. This seems very hacky.
Your approach works as of GLFW 3.2.1-1 in Ubuntu 18.10:
main.cpp
#include <GLFW/glfw3.h>
int main(void) {
GLFWwindow* window;
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
window = glfwCreateWindow(640, 480, __FILE__, NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
while (!glfwWindowShouldClose(window)) {
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Compile and run:
g++ -std=c++11 -Wall -Wextra -pedantic-errors -o main.out main.cpp -lglfw
./main.out
As I hover the borders of the created window, the cursor never changes to resize mode.
GLFW currently has no API for changing that state after the window is created.
When you want to use GLFW, I see two options:
The workaround you already have.
Create a new window when you switch that state.
Use the GLFW native access to obtain the real window handles and implement the feature for each platform (you care about).
All variants don't seem too appealing to me. Option 2 is especially bad because of the way GL contexts are tied to windows in GLFW, it should be possible by using an extra (invisible) window and shared GL contexts, but it will be ugly.
Option 3 has the advantage that it should work flawlessly once it is implemented for all relevant platforms. As GLFW is open source, this enables also option 3b): implement this directly in GLFW and extend the API. You might even be able to get this integrated into the official GLFW version.
You can change the GLFW_RESIZABLE attribute of an existing window with the following code:
bool enable;
glfwSetWindowAttrib(window, GLFW_RESIZABLE, enable);
This works but I highly recommend the other solutions, as this is only if you strictly need to be able to toggle it.
IntBuffer wid = BufferUtils.createIntBuffer(1);
IntBuffer hei = BufferUtils.createIntBuffer(1);
glfwGetWindowSize(window, wid, hei);
int windowWidth = wid.get();
int windowHeight = hei.get(); // I recommend making this public
while(!glfwWindowShouldClose(window)) {
glfwSetWindowSize(window, windowWidth, windowHeight);
// People can still maximize the window ... Comment if you have a solution :)
}
My solution:
// before create:
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
// create window
// ...
// after create
void setResizable(arg) {
if(arg)
glfwSetWindowSizeLimits(window, 0, 0, 0xffff, 0xffff);
else {
int w, h;
glfwGetWindowSize(window, &w, &h);
glfwSetWindowSizeLimits(window, w, h, w, h);
}
}
This worked to me with GLFW 3.3 but be carefull to put it after glfwInit()
int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();
return -1;
}
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
...
}
I'm working on a GLFW application and I noticed a problem when resizing the window.
While the user is scaling the window, the glfwPollEvents() function waits until the user finishes. This means that, during the scaling of the window, the render function isn't called and horrible artifacts are created.
I've worked around this by calling the render function from the main loop as well as the window resize callback:
#include <GLFW/glfw3.h>
static void render(GLFWwindow* window) {
glfwMakeContextCurrent(window);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
static void window_size_callback(GLFWwindow* window, int width, int height) {
render(window);
glViewport(0, 0, width, height);
}
int main(void) {
if (!glfwInit()) {
return -1;
}
GLFWwindow* window = glfwCreateWindow(640, 480, "Terrain chunk render", NULL, NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetWindowSizeCallback(window, window_size_callback);
while (!glfwWindowShouldClose(window)) {
render(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
However, this means that the render function isn't called when the user is holding down the mouse button after having scaled the window without actually moving it. Is there an efficient way of working around this and having the render function called more consistently?
Use two threads, one for polling events and one for rendering. You also might want to use glfwWaitEvents intstead of glfwPollEvents to block the event thread until events are available.
You should move the glfwSetWindowSizeCallback(window, window_size_callback); into your while loop so that the render function is called while you are re-sizing the window. I had the same problem a long time ago.
Edit: It's not recommended to set callbacks in the loop. The frames just need to be redrawn while the window is being resized.