Компилятор шейдеров OpenGL выдает случайные ошибки и не может выполнить рендеринг - PullRequest
0 голосов
/ 03 августа 2020

Я пытаюсь написать простой код для рисования треугольника на экране, но после завершения кода basi c на C ++ я столкнулся с проблемой, когда компилятор шейдера, кажется, выдает случайные ошибки, разные для каждого компилировать, обычно появляясь в следующих строках:

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

Текст обычно представляет собой какую-то на вид случайную команду (ни одной из которых я не смог найти в docs.gl ), или один символ ASCII (включая скобки, знаки препинания, точки с запятой, прописные и строчные буквы). Иногда ничего не выдает, иногда даже выдает segfault, независимо от наличия ошибки.

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

vertex.shader:

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

Я компилирую код на MacOS через CLI, используя:

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

1 Ответ

3 голосов
/ 07 августа 2020

Ваш материал распределения памяти полностью нарушен:

char* buffer = new char(size);

Это выделяет один символ и инициализирует его как size.

То, что вы хотели, было new char[size].

То же самое вы делаете со своими err буферами сообщений.

Более того:

if(!buffer){

Оператор C ++ new работает иначе. Он вызовет исключение, если не сможет выделить память, не вернет указатель NULL.

И, наконец: вы никогда не delete буферы, так что вы будете терять память, когда эта функция вернется. (Обратите внимание, что при использовании правильного синтаксиса массива для выделения, как я показал ранее, правильный способ освобождения - delete [] buffer).

...