I currently have a game with OGL 4.5 and GLFW 3.
I'm trying to make a function that allows toggling between fullscreen and windowed modes. However, it seems in order to accomplish this, I have to destroy the current window and then create a new one in the same pointer (I red this in the GLFW documentation).
Although this works and I can swap between the two modes, it causes some crucial parts of the engine to stop drawing once the swap happens.
Due to this, I would like to know if there is some kind of way to enable / disable fullscreen without destroying the window and creating a new one.
This is the code of the function:
void TMooseEngine::toggleFullscreen()
{
_fullscreen = !_fullscreen;
glfwDestroyWindow(window);
delete _shader;
delete _skybox;
//delete _particulas;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
if(_fullscreen){ //change to fullscreen
window = glfwCreateWindow(_width, _height, "Fate Warriors", glfwGetPrimaryMonitor(), NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,_width,_height);
//culling
glEnable(GL_DEPTH_TEST);
glViewport(0,0,_width,_height);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
_shader = new Shader();
_skybox = new Skybox();
initUI();
}
else{ //change to windowed
window = glfwCreateWindow(_width, _height, "Fate Warriors", NULL, NULL);
glfwMakeContextCurrent(window);
glViewport(0,0,_width,_height);
//culling
glEnable(GL_DEPTH_TEST);
glViewport(0,0,_width,_height);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
_shader = new Shader();
_skybox = new Skybox();
initUI();
}
}
According to the documentation of GLFW, you can use the function glfwSetWindowMonitor() to toggle the fullscreen mode of an existing window, without having to destroy and recreate it.
The following command will change the fullscreen status depending on the _fullscreen variable:
glfwSetWindowMonitor(window, _fullscreen ? glfwGetPrimaryMonitor() : NULL, 0, 0, _width, _height, GLFW_DONT_CARE);
Related
So I tried to make an OpenGL project with GLFW and glad in visual studio code, but it would throw and error when I would compile and run the program.
I tried to make 3 triangles in a window, it worked so I tried organizing the VBO, VAO, EBO, shaderProgram, vertexShaderSource, and fragmentShaderSource into individual files, and compiled and ran it, I expected the usual result but would give me a window that is not responding, then it would terminate and give out an error. I'm not sure witch of the files are causing this, but my guess is the main.cpp file:
#include"header/shaderClass.h"
#include"header/VAO.h"
#include"header/VBO.h"
#include"header/EBO.h"
//some vertex and indices arrays here
int main()
{
// Initialize GLFW
glfwInit();
// Tell GLFW what version of OpenGL we are using
// In this case we are using OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Tell GLFW we are using the CORE profile
// So that means we only have the modern functions
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create a GLFWwindow object of 800 by 800 pixels, naming it "YoutubeOpenGL"
GLFWwindow* window = glfwCreateWindow(800, 800, "YoutubeOpenGL", NULL, NULL);
// Error check if the window fails to create
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
// Introduce the window into the current context
glfwMakeContextCurrent(window);
//Load GLAD so it configures OpenGL
gladLoadGL();
// Specify the viewport of OpenGL in the Window
// In this case the viewport goes from x = 0, y = 0, to x = 800, y = 800
glViewport(0, 0, 800, 800);
// Generates Shader object using shaders defualt.vert and default.frag
Shader shaderProgram("default.vert", "default.frag");
// Generates Vertex Array Object and binds it
VAO VAO1;
VAO1.Bind();
// Generates Vertex Buffer Object and links it to vertices
VBO VBO1(vertices, sizeof(vertices));
// Generates Element Buffer Object and links it to indices
EBO EBO1(indices, sizeof(indices));
// Links VBO to VAO
VAO1.LinkVBO(VBO1, 0);
// Unbind all to prevent accidentally modifying them
VAO1.Unbind();
VBO1.Unbind();
EBO1.Unbind();
// Main while loop
while (!glfwWindowShouldClose(window))
{
// Specify the color of the background
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
// Clean the back buffer and assign the new color to it
glClear(GL_COLOR_BUFFER_BIT);
// Tell OpenGL which Shader Program we want to use
shaderProgram.Activate();
// Bind the VAO so OpenGL knows to use it
VAO1.Bind();
// Draw primitives, number of indices, datatype of indices, index of indices
glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0);
// Swap the back buffer with the front buffer
glfwSwapBuffers(window);
// Take care of all GLFW events
glfwPollEvents();
}
// Delete all the objects we've created
VAO1.Delete();
VBO1.Delete();
EBO1.Delete();
shaderProgram.Delete();
// Delete window before ending the program
glfwDestroyWindow(window);
// Terminate GLFW before ending the program
glfwTerminate();
return 0;
}
i have a little problem setting up my glfw overlay properly, i already successfully created an glfw window with transparent background , now i want to make the window also "click-through" so i can access the windows behind it and let it act like an overlay.
sadly i cant figure out how to do this in glfw, my current code to init the window looks like that:
Width = 3440;
Height = 1440;
/* GLFW */
if (!glfwInit()) {
fprintf(stdout, "[GLFW] failed to init!\n");
exit(1);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
/*Topmost and see through*/
glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
glfwSwapInterval(1);
Window = glfwCreateWindow(Width, Height, "Overlay", 0, 0);
glfwMakeContextCurrent(Window);
i also tried with glfw3_native.h given glfwGetX11Window function and tried to do stuff like
void Render::MakeClickable(bool State){
auto X11Window = glfwGetX11Window(Window);
if(State){
}else{
XserverRegion region = XFixesCreateRegion (MainDisplay, NULL, 0);
XFixesSetWindowShapeRegion (MainDisplay, X11Window, ShapeInput, 0, 0, region);
XFixesDestroyRegion (MainDisplay, region);
}
}
but that didn't worked :/
How can I setup my window correctly to ignore my click and let it pass to the windows behind, so i can use it as an overlay?
a new window hint GLFW_MOUSE_PASSTHROUGH was added to GLFW recently to enable this feature.
you can use it like that:
glfwWindowHint(GLFW_MOUSE_PASSTHROUGH, GLFW_TRUE);
My goal is get pixel data from main window. nothing any rendering.
like we see the monitor such as screencapture.
I tried to TRANSPARENT windows, glReadPixel.
so I have a TRANSPARENT windows and context.
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);
//glfwShowWindow(GLwindow);
if (glfwGetWindowAttrib(GLwindow, GLFW_TRANSPARENT_FRAMEBUFFER))
{
// ..
}
glfwSetWindowOpacity(GLwindow, 0.0f);
glfwMakeContextCurrent(GLwindow);
glfwSetKeyCallback(GLwindow, keyCallback);
glewExperimental = GL_TRUE;
GLenum errorCode = glewInit();
But I want get pixel data from GPU without create windows.
So I use wglcreatecontext Get mother window DC, HGLRC.
And When I set bind buffer, It gives runtime error.
if (!glfwInit()) {
std::cerr << "Error: GLFW" << std::endl;
exit(EXIT_FAILURE);
}
HDCC = GetDC(m_hWndCopy);
// HDC TDC = CreateCompatibleDC(HDCC);
HGLRC DC = wglCreateContext(HDCC);
GLuint pbo;
glGenBuffersARB(1, &pbo); <<Error Here
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo);
How can I solve problem?
Any idea or link?
From your question and comment replies I gather, that you want to use OpenGL to grab a screenshot of an arbitrary window? If so, then this is not what OpenGL is meant for. You cannot use OpenGL for taking screenshots reliably.
glReadPixels will work reliably only for things that you did draw with OpenGL in the first place!
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 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.