c-由于非Ascii字符,顶点着色器无法编译?

因此,我开始使用带有glew和GLFW的OpenGL创建游戏引擎,并且在开始使用着色器时几乎立即遇到了问题:

如果不使用它们,则它们将不会被使用或无效.

我一直在用大量其他示例检查我的代码,并且它们都匹配,没有什么看起来不合适,并且我开始用尽了所有的想法和耐心(我一直在努力找出原因,至今已有近一个月)有了这个.

我的主要核心代码在这里:

  #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字符.

解决方法:

我有完全一样的错误.几乎可以肯定这是由于Unicode Byte Order Marks或文本编辑器生成的类似未打印字符.

这些在unicode文件的前几个字符中很常见,但可以在任何地方出现.

您可以在编译之前以编程方式从着色器源字符串中删除这些着色器,但是如果要编译许多着色器,这可能会很昂贵.如果您选择此路线,请参见上面的链接以获取要删除的数据.

一种替代方法是简单地将文件保留为ANSI / ASCII格式.我确信大多数文本编辑器都可以设置/转换格式,但是我将以Notepad++为例,因为这是我用来编辑GLSL的内容:

>打开GLSL文件.
>编码->转换为ANSI. (请注意,仅单击“在ANSI中编码”不会删除字符)
>保存文件.

上面的代码还应该去除其他容易混淆GLSL解析器的字符(通常是C/C++).

您可以通知用户(/开发人员),在调试版本中加载时文件格式不正确.

上一篇:OpenGL学习笔记


下一篇:OpenGL配置GLFW与GLEW的问题