Как нарисовать при изменении размера окна GLFW?

Всякий раз, когда я изменяю размер окна GLFW, оно не рисуется, пока я изменяю размер окна. Недавно открытая часть окна отображается только после того, как я закончу изменение размера окна. Вы можете увидеть это на картинке ниже:

образ

Вот код для моего приложения. Я использую Windows 10 на Visual Studio 2015

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
void get_resolution(int* window_width, int* window_height);
void initGlfwSettings();
GLFWwindow* initGlfwWindow();
void initGlad();

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
initGlfwSettings();

GLFWwindow* window = initGlfwWindow();

initGlad();

// glad: load all OpenGL function pointers
// ---------------------------------------// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
int width, height;
glfwGetWindowSize(window, &width, &height);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// input
// -----
processInput(window);

// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}

// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size 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 than specified on retina displays.
glViewport(0, 0, width, height);
}

void get_resolution(int* window_width, int* window_height) {
const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

*window_width = mode->width;
*window_height = mode->height;
}

void initGlfwSettings()
{
// 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);#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif
}

GLFWwindow* initGlfwWindow()
{
/*GLFWmonitor* monitor = glfwGetPrimaryMonitor();
int width;
int height;

get_resolution(&width, &height);*/GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "learning opengl", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
exit(1);
}

glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSwapInterval(1);

return window;
}

void initGlad()
{
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
exit(1);
}
}

Объясните любые решения этой проблемы.

3

Решение

Это обработчик событий Windows, не возвращающий управление основному потоку. Это как работает Windows, и вы не можете изменить его.

Однако вы можете переместить все ваши команды рендеринга и команды glfw в другой поток, который не будет остановлен окнами.

0

Другие решения

Вам не нужно создавать отдельный поток.

Вам просто нужно обработать сообщение WM_SIZE и перекрасить, когда это произойдет, к которому можно получить доступ с помощью функции glfwSetWindowSizeCallback. Вы можете вызывать все внутри цикла или просто вызывать части рендеринга и замены буферов.

Windows не возвращается из обработки сообщений во время операции перетаскивания, но продолжает обрабатывать события. Так что вам просто нужно делать все, что вы сделали бы каждый кадр внутри обратного вызова, плюс достаточно, чтобы перенастроить ваши окна просмотра и матрицы и еще много чего для любого нового размера клиента. Этот принцип также работает для оконных движений или чего-либо подобного.

Для Win32 или glfw основной поток:

void MyStart()
{
for glfw set the callback to MyCallback via glfwSetWindowSizeCallback

while(!ShouldExit)
{
some code
MyFrame()
}
}

void MyFrame()
{
do things I normally do per frame

paint this and that

swap buffers
}

void MyCallback()
{
get new client area size
reset viewport or fov
MyFrame();
}

// for windows without glfw
void WndProc()
{
WM_SIZE:
MyCallback();
}
0

По вопросам рекламы [email protected]