OpenGL:使用顶点或片段着色器时不渲染三角形

OpenGL: Triangle is not rendered when vertex or fragment shader is used

我正在尝试使用 OpenGL 在 window 的表面上绘制一个三角形。当我不使用着色器程序时会绘制一个黑色三角形,否则它不会绘制任何内容。没有着色器编译错误。我尝试使用不同版本的 GLSL 但没有成功。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

static const GLfloat g_vertex_buffer_data[] = {
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.0f,  0.5f, 0.0f,
};

unsigned int load_shader(const char *filepath, GLenum type) {
    FILE *file = fopen(filepath, "r");

    if (file == NULL) {
        fprintf(stderr, "Error opening a file %s", filepath);
        return -1;
    }

    fseek(file, 0, SEEK_END);
    long size = ftell(file);
    fseek(file, 0, SEEK_SET);

    GLchar *buf = malloc(sizeof(GLchar) * (size + 1));
    if (buf == NULL) {
        fprintf(stderr, "Cannot allocate memory");
        return -1;
    }

    fgets(buf, size, file);
    fclose(file);
    buf[size] = '[=10=]';

    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, (const GLchar * const*) &buf, NULL);
    glCompileShader(shader);

    GLint is_compiled;
    char info_log[512];
    glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled);

    if (is_compiled == GL_FALSE) {
        glGetShaderInfoLog(shader, 512, NULL, info_log);
        fprintf(stderr, "Shader compilation error: %s", info_log);
        glDeleteShader(shader);
        return -1;
    }

    return shader;
}

int main() {
    if(!glfwInit()) {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return -1;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(1024, 768, "Tutorial 01", NULL, NULL);

    if (window == NULL) {
        fprintf(stderr, "Failed to create a window\n");
        glfwTerminate();
        return 1;
    }

    glfwMakeContextCurrent(window);

    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return 1;
    }

    GLuint vertex_shader = load_shader("simple.vert", GL_VERTEX_SHADER);
    GLuint fragment_shader = load_shader("simple.frag", GL_FRAGMENT_SHADER);
    
    GLuint shader_program = glCreateProgram();
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    glLinkProgram(shader_program);

    GLint is_compiled;
    char info_log[512];
    glGetProgramiv(shader_program, GL_LINK_STATUS, &is_compiled);
    if (is_compiled == GL_FALSE) {
        glGetProgramInfoLog(shader_program, 512, NULL, info_log);
        fprintf(stderr, "Shader program linking error: %s", info_log);
        return 1;
    }
    
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);

    GLuint VertexArrayID, vertexbuffer;
    glGenVertexArrays(1, &VertexArrayID);
    glGenBuffers(1, &vertexbuffer);

    glBindVertexArray(VertexArrayID);

    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    do {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shader_program);
        glBindVertexArray(VertexArrayID);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        // glDisableVertexAttribArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    } while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);

    glDeleteVertexArrays(1, &VertexArrayID);
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteProgram(shader_program);
    glfwTerminate();
    return 0;
}

simple.vert

#version 450 core
layout (location = 0) in vec3 aPos;

void main() {
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

simple.frag

#version 450 core

void main() {
    gl_FlagColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

您没有阅读整个着色器文件,而只是第一行。 fgets 在读取 (n-1) 个字符、读取换行符 或到达文件末尾时停止读取,以先到者为准。 source

如果要读取整个文件,请使用 fread,如 post 中所述:How to read the content of a file to a string in C?

你的片段着色器也有错别字。 gl_FlagColor 应该是 gl_FragColor.