You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:05:21