0

I'm new to OpenGL and I was trying to write a Shader class that loads the shaders from a file and compiles them. The problem is, neither of them are compiling. Both shows error messages like this:

0:1(1): error: syntax error, unexpected $end

I've searched many questions here with the same problem but none of them has worked. The code is below:

Shader.h

#ifndef SHADER_H
#define SHADER_H

#include <GL/glew.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

class Shader {
    public:
        Shader(const GLchar* path);
        GLint Compile(GLenum type);
        GLuint GetID() const;
        const char* GetShaderCode() const;
        void InfoLog() const;
    private:
        GLuint shaderId;
        const char* shaderCode;
        int shaderCodeLength;
        char log[512];

};

#endif

Shader.cpp (the functions where the problem is)

#include "Shader.h"

Shader::Shader(const GLchar* path) {
    std::string shaderString;
    std::ifstream shaderFile;
    std::stringstream shaderStream;

    shaderFile.exceptions(std::ifstream::badbit);

    try {
        shaderFile.open(path);
        shaderStream << shaderFile.rdbuf();
        shaderFile.close();
        shaderString = shaderStream.str();

    } catch (std::ifstream::failure e) {
        std::cout << "Error while reading the file. (Does the file exist?)" << std::endl;

    }


    shaderCode = const_cast<const GLchar*>(shaderString.c_str());
    shaderCodeLength = shaderString.length();
}

GLint Shader::Compile(GLenum type) {
    //Compilates the shader and returns GL_TRUE if succesful or GL_FALSE otherwise.
    GLint status;
    shaderId = glCreateShader(type);
    glShaderSource(shaderId, 1, &shaderCode, &shaderCodeLength);
    glCompileShader(shaderId);
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status);
    glGetShaderInfoLog(shaderId, 512, NULL, log);

    return status;
}

shader.vert

#version 130

in vec2 position;
in vec3 color;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
uniform mat4 trans;

void main() {
    Color = color;
    Texcoord = texcoord;
    gl_Position = trans * vec4(position, 0.0, 1.0);
}

shader.frag

#version 130

in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texKitten;
uniform sampler2D texPuppy;

void main() {
    outColor = mix(texture(texKitten, Texcoord), texture(texPuppy, Texcoord), 0.5);

};

Many people said that the problem was that the shader source ends up a little bit like this: #version 130in vec3 Color;... (but when I print it on the main code, it prints just like it is on the file) and many people are saying that this is the correct way of loading shaders from a file. So, what's wrong in doing this way? Is there a better way?

Jean Catanho
  • 326
  • 7
  • 18
  • You could just use `glShaderSource` in the constructor. That way, you don't need a local copy, and you can query it with `glGetShaderSource`. – Brett Hale Jan 17 '16 at 09:17
  • @BrettHale this works too, since the problem was that glShaderSource and shaderString.c_str() weren't on the same scope. Thank you too. – Jean Catanho Jan 17 '16 at 09:31

1 Answers1

3

shaderCode becomes invalid as soon as the constructor returns because you're saving the result of shaderString.c_str().
Using it is undefined.

Use a std::string member and only do the conversion when you compile the shader, or use dynamic allocation.
The first option is better.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • Wow, finally a nice solution! I was aware of the problem with the shaderString.c_str() but didn't think it was the case here. Anyway, thank you very much! – Jean Catanho Jan 17 '16 at 09:15