添加额外的渲染调用时,GLFW 挂起关闭
GLFW hangs on close when adding an extra rendering call
所以在过去的一段时间里,我一直在尝试学习如何编写openGL编程,尽管很多时候它一直令人费解,但我认为我开始对它的工作原理有了深入的了解。
我一直在使用 GLFW 进行窗口处理和基本输入,并使用 GLEW 访问扩展方法。
我也一直在 www.learnopengl.com 学习本教程,这非常有用。不过,最近我一直在花一些时间尝试创建一些基本的抽象来绘制到屏幕。当我抽象出教程提供的一些代码时,一切都很好(我仍然在"入门"的坐标系部分(。
这样做之后,我决定模拟一个简单的 UI 覆盖会很好,我只有一个函数,可以在 2-D 而不是 3-D 中将矩形绘制到屏幕上,并且只是漂浮在屏幕上的其他所有内容之上。最终,我得到了一些东西,为UI和3-D对象使用不同的着色器。它成功地在其他所有内容之上的屏幕上绘制了一个彩色矩形,但不幸的是,我遇到了一个奇怪的问题,每当我尝试通过将 glfwSetWindowClose调用设置为 true 来关闭窗口时,窗口可以无限期挂起。
每当我删除绘制简单二维矩形的调用时,这个挂起就会消失,窗口会立即按预期关闭。有没有人知道为什么会这样?
主.cpp
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// GL includes
#include "shader.h"
// GLM Mathemtics
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// Other Libs
#include <SOIL.h>
#include "glfw_x360_button_mappings.h"
#include "cube.h"
#include "texture.h"
// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void handleControllerInput(GLFWwindow* window);
// GLOBALS!!!
const unsigned int MONITOR_WIDTH = 1920;
const unsigned int MONITOR_HEIGHT = 1080;
const unsigned int SCREEN_WIDTH = 800;
const unsigned int SCREEN_HEIGHT = 600;
float camera_z = -3.0f;
float camera_x = 0.0f;
// The MAIN function, from here we start our application and run our Game loop
int main()
{
// Init GLFW
glfwInit();
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);
GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed
// TODO: Make window position adapt to any sized window.
glfwSetWindowPos(window, (MONITOR_WIDTH / 2) - (SCREEN_WIDTH / 2), (MONITOR_HEIGHT / 2) - (SCREEN_HEIGHT / 2));
glfwMakeContextCurrent(window);
// Set the required callback functions
glfwSetKeyCallback(window, key_callback);
// Initialize GLEW to setup the OpenGL Function pointers
glewExperimental = GL_TRUE;
glewInit();
// Define the viewport dimensions
glViewport(0, 0, 800, 600);
// Setup OpenGL options
glEnable(GL_DEPTH_TEST);
// Setup and compile our shaders
GLuint vert_id = buildShader("shader.vert", GL_VERTEX_SHADER);
GLuint frag_id = buildShader("shader.frag", GL_FRAGMENT_SHADER);
GLuint shader_program_id = buildProgram(vert_id, frag_id);
glDeleteShader(vert_id);
glDeleteShader(frag_id);
vert_id = buildShader("shader_ui.vert", GL_VERTEX_SHADER);
frag_id = buildShader("shader_ui.frag", GL_FRAGMENT_SHADER);
GLuint ui_shader_program_id = buildProgram(vert_id, frag_id);
glDeleteShader(vert_id);
glDeleteShader(frag_id);
// World space positions of our cubes
glm::vec3 cubePositions[] = {
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(2.0f, 5.0f, -15.0f),
glm::vec3(-1.5f, -2.2f, -2.5f),
glm::vec3(-3.8f, -2.0f, -12.3f),
glm::vec3(2.4f, -0.4f, -3.5f),
glm::vec3(-1.7f, 3.0f, -7.5f),
glm::vec3(1.3f, -2.0f, -2.5f),
glm::vec3(1.5f, 2.0f, -2.5f),
glm::vec3(1.5f, 0.2f, -1.5f),
glm::vec3(-1.3f, 1.0f, -1.5f)
};
// Load and create a texture
GLuint texture1 = create_texture("container.jpg");
GLuint texture2 = create_texture("awesomeface.png");
glm::mat4 view_matrix;
glm::mat4 view_matrix_origin;
glm::mat4 projection_matrix;
view_matrix_origin = glm::translate(view_matrix, glm::vec3(0.0f, 0.0f, 0.0f));
projection_matrix = glm::perspective(45.0f, (float) 512 / (float) 512, 0.1f, 1000.0f);
GLint view_matrix_location = glGetUniformLocation(shader_program_id, "view");
GLint projection_matrix_location = glGetUniformLocation(shader_program_id, "projection");
glUseProgram(shader_program_id);
glUniformMatrix4fv(projection_matrix_location, 1, GL_FALSE, glm::value_ptr(projection_matrix));
Cube test_cube;
init_cube(&test_cube, cube_vertices, sizeof(cube_vertices));
// Game loop
while(!glfwWindowShouldClose(window))
{
// Check and call events
glfwPollEvents();
handleControllerInput(window);
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program_id);
// Bind Textures using texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glUniform1i(glGetUniformLocation(shader_program_id, "ourTexture1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUniform1i(glGetUniformLocation(shader_program_id, "ourTexture2"), 1);
glUniform1f(glGetUniformLocation(shader_program_id, "time"), glfwGetTime());
view_matrix = glm::translate(view_matrix_origin, glm::vec3(camera_x, 0.0f, camera_z));
glUniformMatrix4fv(view_matrix_location, 1, GL_FALSE, glm::value_ptr(view_matrix));
/* THIS IS THE OFFENDING DRAW CALL
* IF REMOVED THE WINDOW STOPS HANGING ON CLOSE */
draw_rect(ui_shader_program_id, glm::vec2(0.0f, 0.0f));
for (GLuint i = 0; i < 10; i++)
{
GLfloat angle = glfwGetTime() * 25.0f;
draw_cube(&test_cube, shader_program_id, cubePositions[i], angle);
}
// Swap the buffers
glfwSwapBuffers(window);
}
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);
}
}
void handleControllerInput(GLFWwindow* window)
{
if (glfwJoystickPresent(GLFW_JOYSTICK_1))
{
int size;
const unsigned char* results = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &size);
if (get_current_button_pressed(results, size) == X360_DPAD_DOWN)
{
camera_z += 0.001f;
}
else if (get_current_button_pressed(results, size) == X360_DPAD_UP)
{
camera_z -= 0.001f;
}
if (get_current_button_pressed(results, size) == X360_DPAD_LEFT)
{
camera_x -= 0.001f;
}
else if (get_current_button_pressed(results, size) == X360_DPAD_RIGHT)
{
camera_x += 0.001f;
}
if (get_current_button_pressed(results, size) == X360_B_BUTTON)
{
camera_z = -3.0f;
camera_x = 0.0f;
}
if (get_current_button_pressed(results, size) == X360_BACK_BUTTON)
{
glfwSetWindowShouldClose(window, true);
}
}
}
矩形.h
#ifndef RECT_H
#define RECT_H
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
const GLfloat rect_vertices[] = {
0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, 0.5f, 1.0f, 0.7f, 0.0f,
-0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
0.75f, -0.5f, 1.0f, 0.7f, 0.0f,
};
void draw_rect(GLuint shader_program_id, glm::vec2 position);
#endif
矩形.cpp
#include "rect.h"
void draw_rect(GLuint shader_program_id, glm::vec2 position)
{
glUseProgram(shader_program_id);
GLuint vao, vbo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(rect_vertices), rect_vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*) 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(2 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
//glm::mat4 model;
//glm::mat4 view;
//glm::mat4 projection;
//model = glm::translate(model, glm::vec3(position, 0.0f));
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "model"), 1, GL_FALSE, glm::value_ptr(model));
//view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "view"), 1, GL_FALSE, glm::value_ptr(view));
//projection = glm::ortho(0, 800, 0, 600, 1, 1000);
//glUniformMatrix4fv(glGetUniformLocation(shader_program_id, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
shader_ui.vert
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec3 color;
out vec3 fragColor;
void main()
{
gl_Position = vec4(position, 0.0f, 1.0f);
fragColor = color;
}
shader_ui.碎片
#version 330 core
in vec3 fragColor;
out vec4 color;
void main()
{
color = vec4(fragColor, 1.0f);
}
如果我未能提供任何相关代码,请告诉我。我认为这涵盖了可能剖析问题所在所需的一切,但如果没有,我很乐意添加任何内容。
您的 draw_rect(( 函数每帧分配一个新的顶点缓冲区,并且永远不会释放它。似乎在运行主循环一小段时间后,已经积累了足够多的这些 VBO,以至于在程序终止时释放它们需要相当长的时间。这应该是导致挂起的原因。
要解决此问题,只需在初始化时创建一个 VBO 并在调用 glDrawArrays(( 之前绑定它。当程序使用 glDeleteBuffers(( 终止时,您可以释放它。
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 在C++和 Python 程序中使用命名管道的 IPC 挂起
- 设置变量时C++程序挂起
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 有时ShowWindow从不调用OnShowWindow,主应用程序挂起
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- WTSFreeMemory在启动期间从服务调用时挂起-我应该省略吗
- 添加额外的渲染调用时,GLFW 挂起关闭