Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm writing a rather simple "ShaderManager" which aids me with loading shaders in Open GL, altough I am having a few issues:

  1. The shaders don't link correctly
  2. The the attributes don't bind

Here's the output of my program:

The shaders did not link correctly.
Could not bind attribute: v_coord3d
Could not bind attribute: v_color
Could not bind uniform: mvp

And here's the relevant code and header file...

void ShaderManager::create_program(std::string name)  {
    GLuint vertexshader;
    GLuint fragmentshader;

    GLint link_ok = GL_FALSE;

    if ((vertexshader = create_shader(name + ".v.glsl", GL_VERTEX_SHADER)) == 0)  {
        print_shader_errors(&vertexshader);
    }

    if ((fragmentshader = create_shader(name + ".f.glsl", GL_FRAGMENT_SHADER)) == 0)  {
        print_shader_errors(&fragmentshader);
    }

    program_values.emplace_back(glCreateProgram());
    program_keys.emplace_back(name);
    glAttachShader(program_values[program_values.back()], vertexshader);
    glAttachShader(program_values[program_values.back()], fragmentshader);
    glLinkProgram(program_values[program_values.back()]);

    glGetProgramiv(program_values[program_values.back()], GL_LINK_STATUS, &link_ok);

    if (!link_ok)  {
        std::cout << "The shaders did not link correctly." << "\n";
    }
}


bool ShaderManager::bind_attribute(std::string shader_name, std::string attribute_name)  {
    GLuint attribute = glGetAttribLocation(get_program(shader_name), attribute_name.c_str());

    if (attribute != -1)  {
        attribute_values.emplace_back(attribute);
        attribute_keys.emplace_back(attribute_name);

        return true;
    }

    std::cout << "Could not bind attribute: " << attribute_name << "\n";

    return false;
}

// bind uniform function is much the same as the above

class ShaderManager {
    public:
        ShaderManager();
        virtual ~ShaderManager();

        static GLuint get_program(std::string shader_name);
        static int get_index_of_program_key(std::string program_name);

        static void create_program(std::string name);
        static bool bind_attribute(std::string shader_name, std::string attribute_name);
        static bool bind_uniform(std::string shader_name, std::string uniform_name);

    protected:
    private:
        static std::vector<GLuint> program_values;
        static std::vector<std::string> program_keys;

        static std::vector<GLuint> attribute_values;
        static std::vector<std::string> attribute_keys;

        static std::vector<GLuint> uniform_values;
        static std::vector<std::string> uniform_keys;

        static void print_shader_errors(GLuint *shader);
        static const char* file_read(std::string filename);
        static GLuint create_shader(std::string filename, GLenum type);
};

Here's the code which actually calls the functions:

ShaderManager::create_program("shader");
ShaderManager::bind_attribute("shader", "v_coord3d");
ShaderManager::bind_attribute("shader", "v_color");
ShaderManager::bind_uniform("shader", "mvp");

Another issue I have is that I can't access a string in a vector list with program_names[0], anyone know why?

share|improve this question
add comment

3 Answers 3

up vote 3 down vote accepted

Are you sure, this is correct?

glAttachShader(program_values[program_values.back()], vertexshader);
glAttachShader(program_values[program_values.back()], fragmentshader);
glLinkProgram(program_values[program_values.back()]);

glGetProgramiv(program_values[program_values.back()], GL_LINK_STATUS, &link_ok);

I am not OpenGL expert, but you probably mean this:

glAttachShader(program_values.back(), vertexshader);
glAttachShader(program_values.back(), fragmentshader);
glLinkProgram(program_values.back());

glGetProgramiv(program_values.back(), GL_LINK_STATUS, &link_ok);
share|improve this answer
    
+1 Thanks! I thought the std::vector.back() function got the index of the last element, not the actual element itself. I now know otherwise. Thanks! - Fixed all my problems :) (I'm still really new to c++) –  Darestium Aug 10 '12 at 22:09
add comment

Use glGetProgramInfoLog to get a log from the linker and understand what is wrong.

char errbuf[4096];
GLsizei len;

glGetProgramInfoLog(program_values[program_values.back()], sizeof(errbuf), &len, errbuf);
glGetProgramiv(program_values[program_values.back()], GL_LINK_STATUS, &link_ok);
if (!link_ok)  {
    std::cout << errbuf << std::endl;
    std::cout << "The shaders did not link correctly." << std::endl;
}

I assume you are not using glGetShaderInfoLog in the compilation stage either, so I suggest you do that, too.

share|improve this answer
    
I've added the suggested code you listed above, it doesn't add anything new to the output. I am indeed using the glGetShaderLogInfo() in the compilation stage. –  Darestium Aug 10 '12 at 7:03
    
@Darestium there is nothing inherently wrong with the code you showed so far. If the program does not link and nothing is printed, it might be a bug in your drivers. The problem might also lie in create_shader(), or in the actual shaders. Can you maybe post these? –  Sam Hocevar Aug 10 '12 at 14:15
    
+1 The problem did lay in my code where I used std::vector[std::vector.back()], I thought the .back() function returned the last element in the list - not the actual element itself. Thanks for the help. –  Darestium Aug 10 '12 at 22:12
add comment

Shaders not linking can be caused by a few things. One of them is that the shaders are not comiled correctly. The tool I use for finding problems with my shaders is gDEBugger (there are two versions to go with, you can read that question/answer to find out more, I found that the original (older) version has worked better for me). I recommend you download this and see what errors are being reported in your shader loading.

You can also have your program output the last error code after each operation. To see where things might be going wrong. Though, I've found at least one time where my shaders were not linking and no errors were being reported with my code. But once I got it loaded up in gDEBugger, I was able to find the issue.

share|improve this answer
    
+1 Thanks for the tip, this tool will defiantly come in use. –  Darestium Aug 10 '12 at 22:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.