简体   繁体   中英

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

I'm trying to draw a triangle on the surface of a window with OpenGL. A black triangle is drawn when I don't use a shader program otherwise it draws nothing. There are no shader compilation errors. I tried to use different versions of GLSL with no success. Here is the code:

#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] = '\0';

    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);
}

You are not reading your whole shader file but just the first line. fgets stops reading when either (n-1) characters are read, the newline character is read , or the end-of-file is reached, whichever comes first. source

If you want to read the whole file, use, for example, fread as described in this post: How to read the content of a file to a string in C?

There is also a typo in your fragment shader. gl_FlagColor should be gl_FragColor .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM