AstroHawking1090
AstroHawking1090

Reputation: 35

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

I am following the tutorials at learnopengl.com and their shaders have been put directly into a const char*. When I try to put the same code into a shader file, later reading it into a const char*, with all the code the same, glGetShaderiv() generates a syntax error.

This is the error: ERROR: 0:1: '' syntax error: illegal extended ASCII character (0xdd).

However, this error does not come up when the code is put directly into a const char*

here is the const char* code vs my code

const char* :

    const GLchar* vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 position;\n"
    "void main()\n"
    "{\n"
    "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
    "}\0";

const GLchar* orangeFragmentShaderSource = "#version 330 core\n"
    "out vec4 color;\n"
    "void main()\n"
    "{\n"
    "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";

const GLchar* yellowFragmentShaderSource = "#version 330 core\n"
    "out vec4 color;\n"
    "void main()\n"
    "{\n"
    "color = vec4(1.0f, 1.0f, 0.0f, 1.0f); // The color yellow \n"
    "}\n\0";

my vertex file:

      #version 330 core

      layout (location = 0) in vec3 position;

      void main() {

      gl_Position = vec4(position.x, position.y, position.z, 1.0);

   }

my yellow fragment shader:

      #version 430 core

      out vec4 colour;

      void main() {

      colour = vec4(1.0f, 1.0f, 0.0f, 1.0f);

  }

my orange fragment shader:

     #version 430 core

    out vec4 colour;

    void main() {

    colour = vec4(1.0f, 1.0f, 0.0f, 1.0f);

 }

and also, here is the code that i use to convert my shaders to strings:

      std::ifstream shaderFile(filePath);
      std::stringstream tmp;

      std::string fileContents = "";
      std::string line = "";

      while (std::getline(shaderFile, line)) fileContents += line + "\n";

      return fileContents + "\0";

and here is another method that I have tried to read from my file

   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>());

my shader compilation code:

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

I have no idea why my string does not work It all looks the same when I outputted the string to console. Can someone pls help me?

Upvotes: 1

Views: 1869

Answers (1)

Columbo
Columbo

Reputation: 6766

When you call tmp.c_str() you receive a pointer to the string owned by tmp.

When you then call tmp = something_else; a new chunk of memory is allocated to hold the new string, and the pointer (e.g. vertexShaderSource) is now invalid. It's known as a dangling pointer.

A simple fix would be to change:

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();

to:

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();

By using 3 different tmp std::string you avoid the problem of the old contents getting invalidated.

Upvotes: 2

Related Questions