OpenGL GLFW无法渲染图形:GL_QUADS绘制正方形无显示问题排查
问题原因与解决方案
你的代码黑屏的核心原因是:你初始化的是OpenGL 3.3核心上下文,但代码里用的是早已被核心模式废弃的固定管线API,具体问题点如下:
- OpenGL 3.2+核心配置移除了
glBegin/glEnd这种立即渲染模式,也不再支持glLoadIdentity、glOrtho这类固定管线矩阵操作,这些调用在核心上下文里会被忽略。 GL_QUADS图元类型在核心模式中已被移除,即使是兼容模式,新版本OpenGL也推荐用三角形图元(如GL_TRIANGLE_FAN或GL_TRIANGLES)替代。
快速修复方案(兼容模式)
如果只是想验证代码逻辑,把GLFW的上下文配置改成兼容模式即可:
修改这一行:
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
为:
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
这样旧的立即模式代码就能正常运行,屏幕上会显示灰色正方形。
推荐方案(现代OpenGL流程)
长期学习建议使用现代OpenGL的VAO/VBO+着色器流程,以下是适配你的需求的完整代码:
#include <iostream> #define GLEW_STATIC #include <GL/glew.h> #include <GLFW/glfw3.h> const GLint WIDTH = 800, HEIGHT = 600; // 顶点着色器源码 const char* vertexShaderSource = R"( #version 330 core layout (location = 0) in vec2 aPos; void main() { gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); } )"; // 片段着色器源码 const char* fragmentShaderSource = R"( #version 330 core out vec4 FragColor; void main() { FragColor = vec4(0.5f, 0.5f, 0.5f, 1.0f); } )"; 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_TRUE); GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Isosurface Stuffing", nullptr, nullptr); int screenWidth, screenHeight; glfwGetFramebufferSize(window, &screenWidth, &screenHeight); if (window == nullptr) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; if (GLEW_OK != glewInit()) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } // 编译顶点着色器 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); glCompileShader(vertexShader); // 检查编译错误 int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog); std::cout << "Vertex shader compile error:\n" << infoLog << std::endl; } // 编译片段着色器 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog); std::cout << "Fragment shader compile error:\n" << infoLog << std::endl; } // 链接着色器程序 GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog); std::cout << "Shader program link error:\n" << infoLog << std::endl; } // 删除临时着色器对象 glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // 正方形顶点数据(用两个三角形组成) float vertices[] = { 100.0f/screenWidth*2 -1, 100.0f/screenHeight*2 -1, // 左下角 200.0f/screenWidth*2 -1, 100.0f/screenHeight*2 -1, // 右下角 200.0f/screenWidth*2 -1, 200.0f/screenHeight*2 -1, // 右上角 100.0f/screenWidth*2 -1, 200.0f/screenHeight*2 -1 // 左上角 }; // 索引数据(三角列表) unsigned int indices[] = { 0, 1, 2, // 第一个三角形 0, 2, 3 // 第二个三角形 }; GLuint VAO, VBO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 设置顶点属性指针 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // 解绑(VAO绑定状态下解绑VBO不影响,EBO会存在VAO里) glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); while (!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(shaderProgram); glBindVertexArray(VAO); // 用索引绘制6个顶点(两个三角形) glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glfwPollEvents(); glfwSwapBuffers(window); } // 释放资源 glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteProgram(shaderProgram); glfwTerminate(); return 0; }
代码说明:
- 使用了
#version 330 core的着色器,符合核心上下文要求 - 把窗口坐标转换为OpenGL的标准化设备坐标(NDC),替代了旧的
glOrtho矩阵 - 用
GL_TRIANGLES图元配合索引缓冲(EBO)绘制正方形,这是现代OpenGL的标准方式
内容的提问来源于stack exchange,提问作者ronalama
相关产品推荐
相关产品推荐

