【问题标题】:OpenGL shader complier throws random errors and fails to renderOpenGL着色器编译器抛出随机错误并且无法渲染
【发布时间】:2020-11-23 08:20:04
【问题描述】:

我正在尝试编写一个简单的代码来在屏幕上绘制一个三角形,但是在完成 C++ 中的基本代码之后,我遇到了一个问题,即着色器编译器似乎抛出随机错误,通常在每次编译时都不同出现如下:

failed to compile shader:: Operation timed out
ERROR: 0:X: 'text' : syntax error: syntax error
: Operation timed out

文本通常是某种看似随机的命令(我在docs.gl 中找不到),或者是单个 ASCII 字符(包括括号、标点符号、分号、大写和小写字母)。有时,它不会抛出任何东西,有时,它甚至会抛出一个段错误,而不管是否存在错误。

main.cpp:

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>

int loadShader(const char* path, unsigned int type){
    FILE* file = fopen(path,"r");

    if(file==NULL){
        printf("\033[31mERROR:\033[0m failed to load shader file: %s\n", path);
        return 0;
    }
    fseek(file, 0L, SEEK_END);
    long size = ftell(file);
    char* buffer = new char[size];
    rewind(file);

    if(!buffer){
        fclose(file);
        printf("\033[31mERROR:\033[0m failed to allocate memory to load shader file: %s\n", path);
        return 0;
    }

    if(1!=fread(buffer, size, 1, file)){
        fclose(file);
        printf("\033[31mERROR:\033[0m failed to read shader file: %s\n", path);
        return 0;
    }

    unsigned int shader = glCreateShader(type);
    glShaderSource(shader, 1, &buffer, (int*)&size);
    glCompileShader(shader);    
    int status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if(!status){
        char err[1024];
        glGetShaderInfoLog(shader, 1024, NULL, err);
        printf("\033[31mERROR:\033[0m failed to compile shader: %s\n", err);
    }
    std::cout<<"loaded shader successfully"<<std::endl;
    delete [] buffer;
    return shader;
}

int main(void){
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    GLFWwindow* window = glfwCreateWindow(800, 600, "Aimless", nullptr, nullptr); // Windowed
    //GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", glfwGetPrimaryMonitor(), nullptr); // Fullscreen
    
    glfwMakeContextCurrent(window);

    glewExperimental = GL_TRUE;
    glewInit();

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    
    GLuint vertexShader = loadShader("vertex.shader", GL_VERTEX_SHADER);
    GLuint fragmentShader = loadShader("fragment.shader", GL_FRAGMENT_SHADER);
    
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);


    while(!glfwWindowShouldClose(window)){

        float vertices[] = {
             0.0f,  0.5f,// vertex 1
             0.5f, -0.5f,// vertex 2
            -0.5f, -0.5f // vertex 3
        };
        GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(posAttrib);

        GLuint vao;
        glGenVertexArrays(1,&vao);
        glBindVertexArray(vao);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        
        glfwSwapBuffers(window);
        glfwPollEvents();
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, GL_TRUE);
    }

    glfwTerminate();
    return 0;
}

顶点着色器:

#version 150 core

in vec2 position;

void main()
{
     gl_Position = vec4(position, 0.0, 1.0);
}

fragment.shader:

#version 150 core

out vec4 color;

void main(){
    color = vec4(1.0, 1.0, 1.0, 1.0);
}

我正在使用 CLI 在 MacOS 上编译代码:

clang++  -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -lglfw -lglew main.cpp -o main.o

【问题讨论】:

    标签: c++ macos opengl glfw glew


    【解决方案1】:

    你的内存分配完全坏了:

    char* buffer = new char(size);
    

    分配单个字符并将其初始化为size

    你想要的是new char[size]

    您正在使用 err 消息缓冲区做同样的事情。

    此外:

    if(!buffer){
    

    这不是 C++ new 运算符的工作方式。如果不能分配内存,会抛出异常,不返回NULL指针。

    最后:你永远不会delete你的缓冲区,所以当这个函数返回时你会泄漏内存。 (注意,如前所述,当使用正确的数组语法进行分配时,正确的释放方法是delete [] buffer

    【讨论】:

    • 那是……奇怪。在使用一些 std::cout 进行调试后,在您和我的示例中,文件似乎已成功加载到 buffer,所以我说这不是问题。着色器编译器输出乱码的问题仍然存在,您的解决方案很困难。
    • "在使用一些 std::cout 进行调试后,在您和我的示例中,文件似乎已成功加载到缓冲区中,"只是在您的代码中,您处于未定义的行为状态并且可能已经覆盖了任何数据结构。对 GL 错误使用 perror 也不起作用,这仅适用于标准库中的 errno。难怪它可能会报告“操作超时”等奇怪的东西。
    • 对,我将用常规的 printf 替换它们并在此处更新代码。我怀疑我已经覆盖了它们。原来的问题还没有解决。
    • 您还告诉编译器您的源字符串将以 NUL 结尾,但除非您可以保证在文本文件的末尾放置一个 0 字节(没有人这样做,而且不是用普通的文本编辑器真的很容易做到),但事实并非如此。
    • 嗯,这可以很容易地添加到主代码本身。着色器的代码或多或少是独立的,所以我不明白为什么要添加它。
    猜你喜欢
    • 1970-01-01
    • 2018-05-30
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多