首页 > 解决方案 > OpenGL着色器编译器抛出随机错误并且无法渲染

问题描述

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

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

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

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

片段着色器:

#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++macosopenglglfwglew

解决方案


你的内存分配的东西完全坏了:

char* buffer = new char(size);

这分配了一个字符并将其初始化为size.

你想要的是new char[size]

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

此外:

if(!buffer){

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

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


推荐阅读