2016-03-26 6 views
1

Так что я начал использовать OpenGL с GLEW и GLFW создать игровой движок, и я почти сразу столкнулся с проблемой при запуске работы с шейдерами:Vertex shader не компилируется из-за не-Ascii-символа?

Они не используются или не имеют никакого эффекта, если они используются ,

Я проверял свой код с большим количеством других примеров, и все они совпадают, ничего не выглядят неуместно, и у меня заканчиваются идеи и терпение (я пытался выяснить, почему почти через месяц).

Мой главный основной код здесь:

#include "headers/Default.hpp" 

    //Window width and height variables 
    int windowWidth = 800; 
    int windowHeight = 600; 
    float Aspect = (float)windowWidth/(float)windowHeight; 

    //Buffer width and buffer height 
    int bufferWidth; 
    int bufferHeight; 

    double deltaTime; 
    double currentTime; 
    double newTime; 

    void CalculateDelta() 
    { 
    newTime = glfwGetTime(); 
    deltaTime = newTime - currentTime; 
    currentTime = newTime; 
    } 

    //A call back function to get the window size 
    void UpdateWindowSize(GLFWwindow* window, int width, int height) 
    { 
    windowWidth = width; 
    windowHeight = height; 

    Aspect = (float)windowWidth/(float)windowHeight; 
    } 

    void UpdateFrameBufferSize(GLFWwindow* window, int width, int height) 
    { 
    bufferWidth = width; 
    bufferHeight = height; 
    } 

    //Starts on startup and creates an window context and starts the rendering loop 
    int main() 
    { 
    //Creates an engine startup log to keep 
    CreateStartupLog(); 

    if (!glewInit()) 
    { 
     WriteStartupLog("ERROR: GLEW failed to start\n"); 
     return 1; 
    } 
    else 
    { 
     WriteStartupLog("INFO: GLEW initiated!\n"); 
    } 

    //If glfw is not initiated for whatever reason we return an error 
    if (!glfwInit()) 
    { 
     WriteStartupLog("ERROR: GLFW failed to start\n"); 
     return 1; 
    } 
    else 
    { 
     WriteStartupLog("INFO: GLFW initiated!\n"); 
    } 

    //////////////////////////////////////////////////////////////// 
    //      Window Section      // 
    //////////////////////////////////////////////////////////////// 
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 

    //Gets the primary monitor of the PC and tells OpenGL to use that monitor 
    GLFWmonitor* monitor = glfwGetPrimaryMonitor(); 
    const GLFWvidmode* videoMode = glfwGetVideoMode(monitor); 

    //Creates a GLFW window context that we can work with 
    GLFWwindow* gameWindow = glfwCreateWindow(windowWidth/*videoMode->width*/, windowHeight/*videoMode->height*/, "FireTech Engine", NULL/*monitor*/, NULL); 

    //If the game window is not able to be created, prints an error and terminates the program 
    if (!gameWindow) 
    { 
     WriteStartupLog("ERROR: GLFW could not create a window\n"); 
     glfwTerminate(); 
     return 1; 
    } 
    else 
    { 
     WriteStartupLog("INFO: GLFW created a window!\n\n"); 
    } 

    //Makes the current context 
    glfwMakeContextCurrent(gameWindow); 

    //Sets the window callback function for size 
    glfwSetWindowSizeCallback(gameWindow, UpdateWindowSize); 
    glfwSetFramebufferSizeCallback(gameWindow, UpdateFrameBufferSize); 

    //Initiate GLEW 
    glewExperimental = GL_TRUE; 
    glewInit(); 

    //////////////////////////////////////////////////////////////// 
    // Functions to set up various systems of the game engine // 
    //////////////////////////////////////////////////////////////// 

    //Calls function to create a log file for the game engine 
    CreateEngineLog(); 
    //Calls the function to compile the default shaders 
    CompileDefaultShader(); 
    //Calls the function to get and print out hardware and OpenGL version 
    //PrintHardwareInfo(); 

    //////////////////////////////////////////////////////////////// 
    //      Game Code       // 
    //////////////////////////////////////////////////////////////// 
    Sprite testSprite; 

    //Rendering loop 
    while (!glfwWindowShouldClose(gameWindow)) 
    { 
     CalculateDelta(); 
     glClearColor(0.3, 0.6, 1.0, 0); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     //Viewport and ortho settings 
     glViewport(0, 0, windowWidth, windowHeight); 
     glOrtho(-1, 1, -1/Aspect, 1/Aspect, 0, 1); 

     //Draw a sprite 
     if (GLFW_PRESS == glfwGetKey(gameWindow, GLFW_KEY_F2)) 
     { 
      testSprite.DebugDraw(); 
     } 
     else 
     { 
      testSprite.Draw(); 
     } 

     //Draws the stuff we just rendered 
     glfwSwapBuffers(gameWindow); 
     glLoadIdentity(); 

     //Polls different events, like input for example 
     glfwPollEvents(); 

     if (GLFW_PRESS == glfwGetKey(gameWindow, GLFW_KEY_F1)) 
     { 
      int fps = GetFPS(); 
      printf("FPS: "); 
      printf("%d\n", fps); 

      printf("Frequency: "); 
      printf("%f\n", 1/double(fps)); 
     } 

     if (GLFW_PRESS == glfwGetKey(gameWindow, GLFW_KEY_ESCAPE)) 
     { 
      glfwSetWindowShouldClose(gameWindow, 1); 
     } 
    } 

    glfwTerminate(); 
    WriteEngineLog("PROGRAM EXITED: Window closed"); 
    return 0; 
    } 

Вот код shader.cpp:

 #include "../headers/Default.hpp" 

    string ReadShaderFile(char* path) 
    { 
    ifstream shaderFile; 
    shaderFile.open(path, std::ifstream::in); 
    string output; 

    if (shaderFile.is_open()) 
    { 
     printf("Opened shader file located at: \"%s\"\n", path); 

     while (!shaderFile.eof()) 
     { 
      output += shaderFile.get(); 
     } 

     printf("Successfully read shader file located at: \"%s\"\n", path); 
    } 
    else 
    { 
     WriteEngineLog("ERROR: Could not read shader file!\n"); 
    } 

    shaderFile.close(); 
    return output; 
    } 

    Shader::Shader() 
    { 
    WriteEngineLog("WARNING: There was no path to any GLSL Shader files\n"); 
    } 

    Shader::Shader(char* VertexShaderPathIn, char* FragmentShaderPathIn) 
    { 
    string vertexShaderString = ReadShaderFile(VertexShaderPathIn); 
    string fragmentShaderString = ReadShaderFile(FragmentShaderPathIn); 

    //Prints out the string to show the shader's code 
    printf("\n%s\n", vertexShaderString.c_str()); 
    printf("\n%s\n", fragmentShaderString.c_str()); 

    //Creates the GLchars needed to input the shader code 
    const GLchar* vertex_shader = vertexShaderString.c_str(); 
    const GLchar* fragment_shader = fragmentShaderString.c_str(); 

    //Creates a vertex shader and compiles it 
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    WriteEngineLog("Blank vertex shader created\n"); 
    glShaderSource(vertexShader, 1, &vertex_shader, NULL); 
    WriteEngineLog("Vertex shader given source\n"); 
    glCompileShader(vertexShader); 

    //Compilation error checking begions here 
    GLint isVertexCompiled = 0; 
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isVertexCompiled); 
    if (isVertexCompiled == GL_FALSE) 
    { 
     //Gets the length of the log 
     GLint maxLength = 0; 
     glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); 

     //Creates and writes the log to the errorLog 
     GLchar* errorLog = (GLchar*)malloc(maxLength); 
     glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &errorLog[0]); 

     //Writes to the engine log with the shader error 
     WriteEngineLog("ERROR: Vertex shader failed to compile!\n"); 
     printf("%s\n", (char*)errorLog); 

     //Frees the errorLog allocation 
     free(errorLog); 

     //Deletes the shader so it doesn't leak 
     glDeleteShader(vertexShader); 

     WriteEngineLog("ERROR: Aborting shader creation.\n"); 
     return; 
    } 
    //Writes in the engine log to report successful compilation 
    WriteEngineLog("Vertex shader successfully compiled!\n"); 

    //Creates a fragment shader 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    WriteEngineLog("Blank fragment shader created\n"); 
    glShaderSource(fragmentShader, 1, &fragment_shader, NULL); 
    WriteEngineLog("Fragment shader given source\n"); 
    glCompileShader(fragmentShader); 

    //Compilation error checking begions here 
    GLint isFragmentCompiled = 0; 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isFragmentCompiled); 
    if (isFragmentCompiled == GL_FALSE) 
    { 
     //Gets the length of the log 
     GLint maxLength = 0; 
     glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); 

     //Creates and writes the log to the errorLog 
     GLchar* errorLog = (GLchar*)malloc(maxLength); 
     glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &errorLog[0]); 

     WriteEngineLog("ERROR: Fragment shader failed to compile\n"); 
     printf("%s\n", (char*)errorLog); 

     //Frees the errorLog allocation 
     free(errorLog); 

     //Deletes the shader so it doesn't leak 
     glDeleteShader(vertexShader); 
     glDeleteShader(fragmentShader); 

     WriteEngineLog("ERROR: Aborting shader creation.\n"); 
     return; 
    } 
    //Writes in the engine log to report successful compilation 
    WriteEngineLog("Fragment shader successfully compiled!\n"); 

    //Creates the final shader product 
    this->Program = glCreateProgram(); 
    WriteEngineLog("Blank shader created\n"); 
    glAttachShader(this->Program, vertexShader); 
    WriteEngineLog("Attatched Vertex shader to the shader\n"); 
    glAttachShader(this->Program, fragmentShader); 
    WriteEngineLog("Attatched Fragment shader to the shader\n"); 
    glLinkProgram(this->Program); 

    /*GLint isLinked = 0; 
    glGetProgramiv(this->Program, GL_LINK_STATUS, (int*)&isLinked); 
    if (isLinked == GL_FALSE) 
    { 
     //Gets the lngth of the shader info log 
     GLint maxLength = 0; 
     glGetProgramInfolog(ShaderOut, GL_INFO_LOG_LENGTH, &maxLength); 

     //Gets and puts the actual log into a GLchar 
     std::vector<GLchar> infoLog(maxLength); 
     glGetProgramInfoLog(ShaderOut, maxLength, &maxLength, &infoLog[0]); 

     //Deletes programs and shaders so they don't leak 
     glDeleteShader(vertexShader); 
     glDeleteShader(fragmentShader); 

     WriteEngineLog((string)infoLog); 

     return; 
    }*/ 

    WriteEngineLog("Shader linked!\n\n"); 

    WriteEngineLog("INFO: Shader created!\n"); 

    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 
    } 

    void Shader::Use() 
    { 
    glUseProgram(this->Program); 
    } 

Вот код quad.cpp:

#include "../headers/Default.hpp" 

    Quad::Quad() 
    { 
    position.x = 0; 
    position.y = 0; 
    scale.x = 1; 
    scale.y = 1; 

    VertexArray = CreateVertexArray(); 
    } 

    //Quad constructor with one arg 
    Quad::Quad(Vector2 Position) 
    { 
    position = Position; 

    VertexArray = CreateVertexArray(); 
    } 

    //Quad constructor with two args 
    Quad::Quad(Vector2 Position, Vector2 Scale) 
    { 
    position = Position; 
    scale = Scale; 

    VertexArray = CreateVertexArray(); 
    } 

    GLuint Quad::CreateVertexArray() 
    { 
    GLfloat Vertices[] = 
    { 
     //VERTICES   //COLORS   //TEXCOORDS 
     0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, //1.0f, 1.0f, //Top Right Vertice 
     0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, //1.0f, 0.0f, //Top Left Vertice 
     -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f//, 0.0f, 0.0f //Bottom Left Vertice 
    }; 

    GLuint vbo, vao; 
    glGenVertexArrays(1, &vao); 
    glGenBuffers(1, &vbo); 

    glBindVertexArray(vao); 

    //Copy vertices into the buffer 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 

    //Attribute Pointers 
    //Position attribute 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); 
    glEnableVertexAttribArray(0); 
    //Color attribute 
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); 
    glEnableVertexAttribArray(1); 

    //Unbinds the VAO 
    glBindVertexArray(0); 

    return vao; 
    } 

    //Quad debug drawing function 
    void Quad::DebugDraw() 
    { 
    //Use the default shader 
    DefaultShader.Use(); 

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
    glBindVertexArray(VertexArray); 

    // draw points 0-3 from the currently bound VAO with current in-use shader 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //CAUSING A CRASH AT THE MOMENT 

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 

    //Unbinds the VAO 
    glBindVertexArray(0); 
    } 

Вот код sprite.cpp:

#include "../headers/Default.hpp" 

    Sprite::Sprite() 
    { 
    position.x = 0; 
    position.y = 0; 
    } 

    Sprite::Sprite(Texture tex) 
    { 
    defaultTexture = tex; 
    currentTexture = tex; 
    } 

    Sprite::Sprite(Texture tex, Vector2 pos) 
    { 
    defaultTexture = tex; 
    currentTexture = tex; 
    position = pos; 
    } 

    Sprite::Sprite(Texture tex, Vector2 pos, Vector2 Scale) 
    { 
    defaultTexture = tex; 
    currentTexture = tex; 
    position = pos; 
    scale = Scale; 
    } 

    void Sprite::Draw() 
    { 
    //Binds the default shader again 
    glBindVertexArray(VertexArray); 

    //Use the default shader 
    DefaultShader.Use(); 

    // draw points 0-3 from the currently bound VAO with current in-use shader 
    glDrawArrays(GL_TRIANGLES, 0, 3); 

    glBindVertexArray(0); 
    } 

Вот мой вершинный шейдер и фрагмент кода шейдера (в произвольном порядке):

//Vertex Shader 
    #version 330 core 

    layout (location = 0) in vec3 position; // The position variable has attribute position 0 
    layout (location = 1) in vec3 color; 

    out vec3 ourColor; 

    void main() 
    { 
     gl_Position = vec4(position, 1.0f); // See how we directly give a vec3 to vec4's constructor 
     ourColor = color; 
    } 

    //Fragment shader 
    #version 330 core 

    in vec3 ourColor; 
    out vec4 color; 

    void main() 
    { 
     color = ourColor; 
    } 

И я получаю предупреждение, что мой шейдер не компилировать ... ошибка в том, что существует не символы ASCII в строке ZERO вершинного шейдера.

+0

'ETLDR' ....... – Alnitak

+2

" 'output + = shaderFile.get();' "Ugh. Вы нашли худший способ загрузить файл: character by character. Чтение целых файлов * действительно * не так сложно в C++. –

+1

Какой шейдер не скомпилировал, вершина или шейдер фрагмента? И, пожалуйста, также опубликуйте вывод glGetShaderinfoLog. – BDL

ответ

1

У меня была такая же ошибка. Это почти наверняка связано с Unicode Byte Order Marks или подобными непечатаемыми символами, сгенерированными текстовыми редакторами.

Они распространены в первых символах файла юникода, но могут встречаться в любом месте.

Вы можете программно удалить эти строки из исходных строк шейдера перед компиляцией, но это может быть дорогостоящим, если вы компилируете много шейдеров. См. Приведенную выше ссылку для передачи данных, если вы идете по этому маршруту.

Альтернативой является просто сохранение файлов в формате ANSI/ASCII. Я уверен, что большинство текстовых редакторов имеют возможность установить/преобразование форматов, но я дам Notepad++ в качестве примера, так как это то, что я использую для редактирования GLSL:

  1. Открыть файл GLSL.
  2. Кодировка -> Конвертировать в ANSI. (Обратите внимание, что просто нажатие «Encode in ANSI» не будет разделять символы)
  3. Сохраните файл.

Вышеупомянутое должно также лишить других символов, подверженных запутыванию парсеров GLSL (и вообще C/C++).

Вы можете сообщить пользователю (/ разработчику), что файлы находятся в неправильном формате при загрузке в отладочных сборках.