M2 MacBook运行OpenGL基础C程序出现黑屏问题求助
问题
我尝试用C语言编写一个基础OpenGL程序来显示三角形,但始终出现黑屏。程序编译链接无错误,着色器程序基础且编译链接正常,本应显示红色三角形。即使着色器有问题,也应该显示glClear和glClearColor设置的颜色,但实际始终黑屏。我尝试过修改OpenGL版本、链接不同文件,但都无效。(我知道OpenGL在新版macOS中已被弃用,但很多人表示基础功能仍可正常工作)
相关代码如下:
main.c
#include <stdio.h> #include <stdlib.h> #include <math.h> //#include <GL/glew.h> #define GL_SILENCE_DEPRECATION #include "win.h" #include "shaders/cshader.h" #include "glew.h" #define GLFW_INCLUDE_GLCOREARB #include "glfw3.h" #include <OpenGL/gl3.h> int main(void) { if( !glfwInit()) { fprintf( stderr, "Failed to initialize GLFW\n" ); return -1; } // create window GLFWwindow* window = createWindow(1280,720); glewExperimental=GL_TRUE; // Needed in core profile if (glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); return -1; } glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); GLuint VertexArrayID; glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); static const GLfloat g_vertex_buffer_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; // This will identify our vertex buffer GLuint vertexbuffer; // Generate 1 buffer, put the resulting identifier in vertexbuffer glGenBuffers(1, &vertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // Give our vertices to OpenGL. glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); Shader shader = ShaderInit(); shader.Load(&shader,"/Users/***/Desktop/coding/gl_test/shaders/tri.vert","/Users/***/Desktop/coding/gl_test/shaders/tri.frag"); glUseProgram(shader.program); glClearColor(0.0f, 0.0f, 0.4f, 0.0f); glfwMakeContextCurrent(window); do{ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glVertexAttribPointer( 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. 3, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); // Draw the triangle ! // Starting from vertex 0; 3 vertices total -> 1 triangle glUseProgram(shader.program); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(0); // Swap buffers if (glGetError() != GL_NO_ERROR){ printf("Err"); } glfwSwapBuffers(window); glfwPollEvents(); } // Check if the ESC key was pressed or the window was closed while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 ); return 0; }
win.c
#include <stdio.h> #include <stdlib.h> #include "/Users/***/Downloads/glew-2.1.0/include/GL/glew.h" #include "/opt/homebrew/Cellar/glfw/3.3.8/include/GLFW/glfw3.h" GLFWwindow* createWindow(int WIDTH, int HEIGHT){ glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // We want OpenGL 4.1 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL // Open a window and create its OpenGL context GLFWwindow* window; // (In the accompanying source code, this variable is global for simplicity) window = glfwCreateWindow( WIDTH, HEIGHT, "graphic", NULL, NULL); if( window == NULL ){ fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible.\n" ); glfwTerminate(); return NULL; } glfwMakeContextCurrent(window);// Initialize GLEW glfwPollEvents(); return window; }
Makefile
LIBS=-L/opt/homebrew/lib -L/Users/***/Downloads/glew-2.1.0/lib -lGL -lglew INC=-I/Users/***/Downloads/glew-2.1.0/include main: gcc main.c win.c shaders/cshader.c `pkg-config --cflags glfw3` $(LIBS) $(INC) -g -Wall -framework Cocoa -framework OpenGL `pkg-config --libs glfw3` -o test
解决方案
1. 修正上下文初始化顺序
main函数中循环前的glfwMakeContextCurrent(window)属于重复调用,且位置错误(createWindow函数中已经完成上下文绑定),直接删除该行即可。
2. 修复Makefile链接参数
macOS环境下不存在-lGL库,该参数会导致无效链接,修改LIBS行:
LIBS=-L/opt/homebrew/lib -L/Users/***/Downloads/glew-2.1.0/lib -lglew
3. 确保着色器输入属性匹配
顶点着色器必须显式声明属性位置,与代码中的glVertexAttribPointer(0)对应。示例顶点着色器tri.vert:
#version 410 core layout(location = 0) in vec3 aPos; void main() { gl_Position = vec4(aPos, 1.0); }
片段着色器tri.frag确保输出红色:
#version 410 core out vec4 FragColor; void main() { FragColor = vec4(1.0, 0.0, 0.0, 1.0); }
4. 完善OpenGL错误检查
单次glGetError()无法捕获所有排队错误,修改为循环检查:
// 放在glfwSwapBuffers之前 GLenum err; while ((err = glGetError()) != GL_NO_ERROR) { fprintf(stderr, "OpenGL错误代码: 0x%04X\n", err); }
5. 调整清屏与深度测试设置
如果清屏颜色仍不显示,可暂时禁用深度测试并简化清屏操作:
// 在glfwSetInputMode后添加 glDisable(GL_DEPTH_TEST);
将循环内的glClear改为:
glClear(GL_COLOR_BUFFER_BIT);
6. 验证着色器编译链接状态
在Shader.Load函数中添加日志输出,确认着色器无静默失败:
- 编译后通过
glGetShaderiv(shader, GL_COMPILE_STATUS, &success)检查状态,失败则用glGetShaderInfoLog输出日志。 - 链接后通过
glGetProgramiv(program, GL_LINK_STATUS, &success)检查状态,失败则用glGetProgramInfoLog输出日志。
内容的提问来源于stack exchange,提问作者shtabbbe
相关产品推荐
相关产品推荐

