4

Problem:

Been struggling to get my code to load external shaders and it is not working. No matter how i rewrite the code and try again i get the same error every time.

The shaders compile but will not link, is there anything that i am doing wrong in this function? The error catching blocks work great btw.

Fragment shader(s) failed to link,  vertex shader(s) failed to link.
ERROR: error(#280) Not all shaders have valid object code.
ERROR: error(#280) Not all shaders have valid object code.

I'm using freeglut, x64 windows 7 and mingw (and I am not using an IDE)

Usage:

In my mainloop I have GLuint programId = loadShader("vertex.shader", "frag.shader"); then I enable it with glUseProgram();

GLuint loadShader(const char * vertex_file_path, const char * fragment_file_path) {

    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    GLuint programId = glCreateProgram();

    GLint status = GL_FALSE;
    int infoLogLength;
    std::string line = "";

    //read in and compile
    std::string vertexShaderCode = "";
    std::ifstream vifs(vertex_file_path);
    if(!vifs.is_open()) {

        while(getline(vifs, line))
            vertexShaderCode += line +"\n";
        vifs.close();
    }

    const char * vertexStream = vertexShaderCode.c_str();

    std::string fragmentShaderCode = "";
    std::ifstream fifs(fragment_file_path);
    if(!fifs.is_open()) {

        while(getline(fifs, line))
            fragmentShaderCode += line +"\n";
        fifs.close();
    }

    const GLchar * fragmentStream = fragmentShaderCode.c_str();

    glShaderSource(vertexShaderId, 1, &vertexStream, NULL);
    glCompileShader(vertexShaderId);   

    glShaderSource(fragmentShaderId, 1, &fragmentStream, NULL);
    glCompileShader(fragmentShaderId);    

    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &status);
    glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
    std::vector<char> vertexShaderErrorMessage(infoLogLength);
    glGetShaderInfoLog(vertexShaderId, infoLogLength, NULL, &vertexShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &vertexShaderErrorMessage[0]);

    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &status);
    glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
    std::vector<char> fragmentShaderErrorMessage(infoLogLength);
    glGetShaderInfoLog(fragmentShaderId, infoLogLength, NULL, &fragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s\n", &fragmentShaderErrorMessage[0]);

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);
    glLinkProgram(programId);
    glUseProgram(programId);

    glGetProgramiv(programId, GL_LINK_STATUS, &status);
    glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);
    std::vector<char> programErrorMessage(std::max(infoLogLength, int(1)) );
    glGetProgramInfoLog(programId, infoLogLength, NULL, &programErrorMessage[0]);
    fprintf(stdout, "%s\n", &programErrorMessage[0]);

    glDeleteShader(vertexShaderId);
    glDeleteShader(fragmentShaderId);

    return programId;
    }

[vertex.shader]

#version 400

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
out vec4 ex_Color;

void main(void) {
    gl_Position = in_Position;
    ex_Color = in_Color;
}

frag.shader

#version 400

in vec4 ex_Color;
out vec4 out_Color;

void main(void) {
   out_Color = ex_Color;
}
iKlsR
  • 2,482
  • 6
  • 25
  • 43
  • Test with a simpler shader, like the ones found [here](http://stackoverflow.com/questions/11122815/opengl-shaders-dont-link-with-shader-program), to find out whether the problem is the shader or the loading code. – Ben Voigt Jul 03 '12 at 21:58
  • the problem isn't the shader, they work perfectly inline. just not when i try to load them and that post was not resolved(he fixed an error and got another one, i dnt want that) that's why i created this one. – iKlsR Jul 03 '12 at 22:03

1 Answers1

3

You only read the files if they failed to open. Right now you're passing empty strings to glShaderSource.

Change the is_open test (better yet, check good() instead of is_open()), and things will probably work.

Change

std::ifstream vifs(vertex_file_path);
if(!vifs.is_open()) { // <<=== BACKWARDS!

    while (getline(vifs, line))
        vertexShaderCode += line + "\n";
    vifs.close();
}

to

{
    std::ifstream vifs(vertex_file_path);
    while(getline(vifs, line))
        vertexShaderCode += line +"\n";
}

Since you're trying to read the whole file, look at some better ways in this question.

Community
  • 1
  • 1
Ben Voigt
  • 260,885
  • 36
  • 380
  • 671
  • i tried both your methods and still the same error, however i am working on the empty string idea. thanks. – iKlsR Jul 03 '12 at 22:06
  • 1
    @iKlsR: What do you mean, "both" my methods? The first one is your *wrong* code. In mine, there is no `if` test at all, the while loop takes care of it. – Ben Voigt Jul 03 '12 at 22:07
  • you said change the is_open() test to good().. i tried that then i tried outing the if test. same error. :( – iKlsR Jul 03 '12 at 22:13
  • @iKlsR: Your existing code looks for a file that is NOT open. Fix the NOT. – Ben Voigt Jul 03 '12 at 22:14
  • @iKlsR: Also, try using a debugger, so you find out if any text gets read from the file. Probably you're missing the path from your filename, or something like that. – Ben Voigt Jul 03 '12 at 22:16
  • hrm. i removed the faulty lines and tried again, stepped through with a debugger, nothing caught,, just the same error each time that they refuse to link, the strings hold the file that i read in, i printf'd them. – iKlsR Jul 03 '12 at 22:21
  • did some more debugging and finally got it to work. thanks. you snippet helped. – iKlsR Jul 07 '12 at 15:51