1
votes

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?

1
how do you pass the std::string to glShaderSource?BDL
Loop over the characters of your strings. Do they contain any non ASCII characters? Check for bytes with values < 0 (for signed chars, or > 127 for unsigned chars). If you copied the text from a website, it may contain non-ASCII characters that look like perfectly valid characters, for example, sometimes they'll use fancy bi-directional quotation marks.Benjamin Lindley
FWIW, 0xdd is a byte pattern used by Microsoft (and possibly others) to indicate a block of memory that has been freed. BDL is right, you need to post the code where you call glShaderSource, you are almost certainly passing in the string incorrectly.Columbo
The string memory gets freed whenever you override tmp. Thus vertexShaderSource and yellowFragmentShaderSource point to invalid adresses.BDL
@GallifreyDW: learn how pointers work. In your case, vertexShaderSource and yellowFragmentShaderSource are both invalid because the memory the are pointing to is no linger valid, because the buffer they are pointing to is managed by the tmp object which you modified after taking the pointer.derhass

1 Answers

2
votes

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.