OpenGL 着色器编译但窗口中未出现渲染

Posted

技术标签:

【中文标题】OpenGL 着色器编译但窗口中未出现渲染【英文标题】:OpenGL shaders compile but no rendering appears in the window 【发布时间】:2022-01-24 01:56:21 【问题描述】:

顶点和片段着色器似乎都在编译,窗口出现并被赋予清晰的颜色,但我无法渲染三角形。我试图只使用 glBegin();顶点()​​; glEnd();作为替代方案,但这也导致没有渲染三角形。

ma​​in.c

#include <stdio.h>
#include <unistd.h>
#include <gfx/shader.h>
#include <gfx/vbo.h>
#include <gfx/vao.h>

GLfloat vertices[] = 
    0.0f,1.0f,0.0f,
    1.0f,1.0f,0.0f,
    -1.0f,-1.0f,0.0f
;

int main(void)
    if(!glfwInit())
        fprintf(stderr, "Unable to init GLFW.\n");
        exit(1);
    
    GLFWwindow *win;
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    win = glfwCreateWindow(SCREENWIDTH, SCREENHEIGHT, "Terraria", NULL, NULL);
    if(win==NULL)
        fprintf(stderr, "Error creating opengl window\n");
        glfwTerminate();
        exit(1);
    
    glfwMakeContextCurrent(win);
    if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        fprintf(stderr, "Unable to init glad\n");
        glfwTerminate();
        exit(1);
    
    glViewport(0, 0, 800, 600);
    glfwSetFramebufferSizeCallback(win, frame_buffer_size_cb);

    struct Shader s = create_shader("resources/shaders/vec2.vs", "resources/shaders/vec2.fs");
    uint32_t vaoID, vboID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(vboID, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);

    while(!glfwWindowShouldClose(win))
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(s.sh);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glVertexAttribPointer(
            0,
            3,
            GL_FLOAT,
            GL_FALSE,
            3*sizeof(GLfloat),
            (void*)0
        );
        glDrawArrays(GL_TRIANGLES, 0,3);
        glDisableVertexAttribArray(0);


        glfwSwapBuffers(win);
        glfwPollEvents();
    
    glfwTerminate();
    return 0;

shader.h

#include <gfx/gfx.h>

struct Shader
    uint32_t sh;
    uint32_t vsh;
    uint32_t fsh;
;

struct Shader create_shader(const char *vs_path, const char *fs_path);

shader.c

#include <gfx/shader.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>

static uint32_t _compile(int8_t id, const char *path, uint16_t type)
    uint32_t sh; //Shader handle or ID
    FILE *fp = fopen(path, "rb"); //Open the shader source code file
    long sz = file_size(fp); //Get the file size
    char *shaderSource; //Create object to holder shader source code
    shaderSource = calloc(sz+1, 1);
    fread(shaderSource, 1, sz, fp); //Read the shader source code into new buffer
    fclose(fp);
    assert(strlen(shaderSource)>0);
    sh = glCreateShader(type);
    glShaderSource(sh, 1, (const GLchar **)&shaderSource, NULL);
    glCompileShader(sh);
    int success;
    char infoLog[512];
    glGetShaderiv(sh, GL_COMPILE_STATUS, &success);
    if (!success)
    
        glGetShaderInfoLog(sh, 512, NULL, infoLog);
        printf("Unable to compile shader id %d\n", id);
    
    free(shaderSource);
    return sh;


struct Shader create_shader(const char *vs_path, const char *fs_path)
    struct Shader h;
    h.vsh = _compile(1,vs_path, GL_VERTEX_SHADER);
    h.fsh = _compile(0,fs_path, GL_FRAGMENT_SHADER);
    h.sh = glCreateProgram();
    glAttachShader(h.sh, h.vsh);
    glAttachShader(h.sh, h.fsh);
    glLinkProgram(h.sh);
    // check for linking errors
    int success;
    char infoLog[512];
    glGetProgramiv(h.sh, GL_LINK_STATUS, &success);
    if (!success) 
        glGetProgramInfoLog(h.sh, 512, NULL, infoLog);
        printf("Unable to link gl program\n");
    
    glDetachShader(h.sh, h.vsh);
    glDetachShader(h.sh, h.fsh);
    glDeleteShader(h.vsh);
    glDeleteShader(h.fsh);
    return h;

顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
void main()
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);

片段着色器

#version 330 core

out vec4 FragColor;

void main()
    FragColor = vec4(1.0,1.0,1.0,1.0);

【问题讨论】:

您已经对着色器编译和链接进行了错误检查,但在主循环中没有任何内容。在主循环中添加一些错误检查。要么你在画黑色,你在向后画,你在相机后面画,或者你忽略了一个错误。 @3Dave 在主循环中检查错误是有意义的。您对如何对主循环中的程序运行错误检查有什么建议吗?我想这不是编译和链接中的着色器错误日志。抱歉,我是 OpenGL 的新手。 glGetError。见khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetError.xml 如果你在你的主循环中放了一堆,比如,在每次gl* 调用之后,你会找到错误的来源。那时有点二进制搜索调试。对于无效操作,每个gl* 函数的帮助页面都会列出错误情况。 那个没有错误,把它放在循环中的每个调用之后。关于这个在相机后面的图,我所有的z值都是0.0f,我想只要视口设置正确,它就不会在右边? 【参考方案1】:

我找到了答案。如果您仔细查看 main,似乎您实际上应该将 glBindBuffer 调用到宏 GL_ARRAY_BUFFER 而不是像我想的那样调用 vbo 句柄。解决这个问题会导致我的程序运行。我的窗口提示也没有生效,因为我在创建窗口后调用它们。

【讨论】:

以上是关于OpenGL 着色器编译但窗口中未出现渲染的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用 OpenGL 编译顶点着色器时会出现着色器编译器错误 #143、#160 和 #216?

OpenGL入门之渲染管线pipeline,着色器Shader

初识OpenGL 链接着色器

初识OpenGL 链接着色器

OpenGL 对象不显示,着色器相关

openGL一些概念02