当我的着色器文件的所有信息都被正确读取到字符串中并且语法正确时,OpenGL为什么会出现语法错误

Why does OpenGL Give a syntax error when all the info of my shader file is read properly into a string and is syntactically correct

本文关键字:语法 错误 OpenGL 为什么 字符串 读取 文件 我的 信息      更新时间:2023-10-16

我正在学习learnopengl.com上的教程,它们的着色器已直接放入const char*中。当我试图将相同的代码放入着色器文件中,稍后将其读取为const char*,并且所有代码都相同时,glGetShaderiv()会生成语法错误。

这是错误:错误:0:1:"语法错误:非法的扩展ASCII字符(0xdd)。

然而,当代码直接放入const char*中时,不会出现此错误

这是const char*代码与我的代码

const char*:

    const GLchar* vertexShaderSource = "#version 330 coren"
    "layout (location = 0) in vec3 position;n"
    "void main()n"
    "{n"
    "gl_Position = vec4(position.x, position.y, position.z, 1.0);n"
    "}";
const GLchar* orangeFragmentShaderSource = "#version 330 coren"
    "out vec4 color;n"
    "void main()n"
    "{n"
    "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);n"
    "}n";
const GLchar* yellowFragmentShaderSource = "#version 330 coren"
    "out vec4 color;n"
    "void main()n"
    "{n"
    "color = vec4(1.0f, 1.0f, 0.0f, 1.0f); // The color yellow n"
    "}n";

我的顶点文件:

      #version 330 core
      layout (location = 0) in vec3 position;
      void main() {
      gl_Position = vec4(position.x, position.y, position.z, 1.0);
   }

我的黄色碎片着色器:

      #version 430 core
      out vec4 colour;
      void main() {
      colour = vec4(1.0f, 1.0f, 0.0f, 1.0f);
  }

我的橙色碎片着色器:

     #version 430 core
    out vec4 colour;
    void main() {
    colour = vec4(1.0f, 1.0f, 0.0f, 1.0f);
 }

此外,这是我用来将着色器转换为字符串的代码:

      std::ifstream shaderFile(filePath);
      std::stringstream tmp;
      std::string fileContents = "";
      std::string line = "";
      while (std::getline(shaderFile, line)) fileContents += line + "n";
      return fileContents + "";

这是我试图从文件中读取的另一种方法

   std::ifstream shaderFile(filePath);
   if (!shaderFile.good()) {
       std::cout << "File failed to load..." << filePath << std::endl;
       std::system("PAUSE");
       std::exit(1);
   }
  return std::string(std::istreambuf_iterator<char>(shaderFile), std::istreambuf_iterator<char>());

我的着色器编译代码:

tmp = convertShaders("VertexShader.vert");
const GLchar *vertexShaderSource = tmp.c_str();
std::cout << vertexShaderSource << std::endl;
tmp = convertShaders("FragmentShaderYellow.frag");
const GLchar *yellowFragmentShaderSource = tmp.c_str();
tmp = convertShaders("FragmentShaderOrange.frag");
const GLchar *orangeFragmentShaderSource = tmp.c_str();
glShaderSource(vertexShaderID, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShaderID);
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
glShaderSource(yellowFragmentShaderID, 1, &yellowFragmentShaderSource, NULL);
glCompileShader(yellowFragmentShaderID);
glGetShaderiv(yellowFragmentShaderID, GL_COMPILE_STATUS, &success);

glShaderSource(orangeFragmentShaderID, 1, &orangeFragmentShaderSource, NULL);
glCompileShader(orangeFragmentShaderID);
glGetShaderiv(orangeFragmentShaderID, GL_COMPILE_STATUS, &success);

我不知道为什么我的字符串不起作用。当我将字符串输出到控制台时,一切看起来都一样。有人能帮我吗?

当您调用tmp.c_str()时,您会收到一个指向tmp拥有的字符串的指针。

当您调用tmp=something_else;分配一个新的内存块来保存新字符串,并且指针(例如vertex ShaderSource)现在无效。它被称为悬空指针。

一个简单的解决方案是改变:

tmp = convertShaders("VertexShader.vert");
const GLchar *vertexShaderSource = tmp.c_str();
std::cout << vertexShaderSource << std::endl;
tmp = convertShaders("FragmentShaderYellow.frag");
const GLchar *yellowFragmentShaderSource = tmp.c_str();
tmp = convertShaders("FragmentShaderOrange.frag");
const GLchar *orangeFragmentShaderSource = tmp.c_str();

至:

tmp = convertShaders("VertexShader.vert");
const GLchar *vertexShaderSource = tmp.c_str();
std::cout << vertexShaderSource << std::endl;
std::string tmp2 = convertShaders("FragmentShaderYellow.frag");
const GLchar *yellowFragmentShaderSource = tmp2.c_str();
std::string tmp3 = convertShaders("FragmentShaderOrange.frag");
const GLchar *orangeFragmentShaderSource = tmp3.c_str();

通过使用3个不同的tmpstd::字符串,可以避免旧内容无效的问题。