0
votes

I'm pretty new to OpenGL and just started with a basic program that has a vertex shader and a fragment shader. Everything worked until i tried to send data from the vertex shader to the fragment shader. I read code online and did it perfectly. i use out in the vertex shader and in in the fragment shader, i looked online everywhere for a solution and could not find a thing, and its hard to debug when you dont know much about GLSL or OpenGL. Here are shaders. ( ill only post the shaders since everything else is working fine. The Vertex

#version 120
varying vec4 ourColor;
attribute vec3 position;

void main()
{
gl_Position = vec4(position, 1.0);
ourColor = vec4(1.0,0.1,0.2,0.5);
}

And the Fragment:

#version 120 
varying vec4 ourColor;

void main()
{
gl_FragColor = ourColor;
}

The error is: Fragment Shader contains a user varying but is linked without a vertex shader. I tried using the flat keyword, and the varying keyword, same result. And thanks in advanced for your time. Also I've tried changing the version and then using in and out, same error. Here is the Shader Code: (its in a shader class, this is Shader.cpp)

     Shader::Shader(const std::string & fileName)
    {
    m_program = glCreateProgram();
    //vertex shader
    m_shaders[0] = CreateShader(LoadShader(fileName + ".vs"), GL_VERTEX_SHADER); 
    m_shaders[0] = CreateShader(LoadShader(fileName + ".fs"),       
            GL_FRAGMENT_SHADER); 


    for(unsigned int i = 0; i < NUM_SHADERS; i++)
        glAttachShader(m_program, m_shaders[i]);


    glBindAttribLocation(m_program, 0, "position");


    glLinkProgram(m_program);
    CheckShaderError(m_program, GL_LINK_STATUS, true, "Error: Program linking failed. ");

    glValidateProgram(m_program);
    CheckShaderError(m_program, GL_VALIDATE_STATUS, true, "Error: Program is invalid. ");
}
//-----------
Shader::~Shader(void)
{
    for(unsigned int i = 0; i < NUM_SHADERS; i++)
    {
        glDetachShader(m_program, m_shaders[i]);
        glDeleteShader(m_shaders[i]);
    }

    glDeleteProgram(m_program);

}
//----------
void Shader::Bind()
{
    glUseProgram(m_program);
}
static GLuint CreateShader(const std::string & text, GLenum shaderType)
{
    GLuint shader = glCreateShader(shaderType);
    if(shader == 0)
    {
        std::cerr << "Error: Shader creation failed! " << std::endl;
    }
    const GLchar* ShaderSourceStrings[1];
    GLint ShaderSourceStringsLengths[1];
    ShaderSourceStrings[0] = text.c_str();
    ShaderSourceStringsLengths[0] = text.length();
    glShaderSource(shader, 1, ShaderSourceStrings, ShaderSourceStringsLengths);
    glCompileShader(shader);
    CheckShaderError(shader, GL_COMPILE_STATUS, false, "Error: Shader compilation failed");
    return shader;
}
//-----------
static std::string LoadShader(const std::string & fileName)
{
    std::ifstream file;
    file.open((fileName).c_str());
    std::string output;
    std::string line;
    if(file.is_open())
    {
        while(file.good())
        {
            getline(file, line);
            output.append(line + "\n");
        }
    }
    else
    {
        std::cerr << "unable to load shader file: " << fileName << std::endl;
    }
    return output;
}
//-----------
static void CheckShaderError(GLuint shader, GLuint flag, bool isProgram, const std::string & errorMessage)
{
    GLint success = 0;
    GLchar error[1024] = {0};
    if(isProgram)
        glGetProgramiv(shader, flag, &success);
    else
        glGetShaderiv(shader, flag, &success);
    if(success == GL_FALSE)
    {
        if(isProgram){
            glGetProgramInfoLog(shader, sizeof(error), NULL, error);
        std::cout << "error from program" << std::endl;
        }
        else{
            glGetShaderInfoLog(shader, sizeof(error), NULL, error);
            std::cout << "error from shader" << std::endl;
        }
            std::cerr << errorMessage << ": '"  << error << "'" << std::endl;
        }
    }
1
You can't mix in/out and attribute/varying. These are similar things but in different versions of GLSL/OpenGL. - BDL
Either version 120 and attribute/varying, or version 150+ and in/out. - pleluron
@BDL: I think you can mix them, since attribute / varying are merely deprecated. Depending on the version they may only be available in compatibility profile. - Dietrich Epp
Also make sure that you're getting the results of glGetShaderInfoLog and glGetProgramInfoLog in debug versions of your code. - Dietrich Epp
"but is linked without a vertex shader" Then your C++ code is to blame. You're not building your program correctly. - Nicol Bolas

1 Answers

2
votes

Final update:

Here's the error.

m_shaders[0] = 
m_shaders[0] = 

Fragment Shader contains a user varying but is linked without a vertex shader.

Linked without a vertex shader? That would definitely cause problems. The code should look something vaguely like this:

GLuint load_shader(GLenum shader_type, ...) {
    GLuint shader = glCreateShader(shader_type);
    ... load shader source code ...
    glCompileShader(shader);
    GLint success;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        // boom
    }
    ... glGetShaderInfoLog ...
    return shader;
}

GLuint load_program(...) {
    GLuint prog = glCreateProgram();
    // Attach both fragment and vertex shader
    glAttachShader(prog, load_shader(GL_VERTEX_SHADER, ...));
    glAttachShader(prog, load_shader(GL_FRAGMENT_SHADER, ...));
    // Then link them together
    glLinkProgram(prog);
    GLint success;
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if (!success) {
        // boom
    }
    ... glGetProgramInfoLog ...
}

It's a fair bit of boilerplate code, and there are a lot of opportunities for the code to contain errors, so it's common for something to be wrong, especially since practically everything in OpenGL is just typedef int GLxxx; or something like that.


In GLSL 120, in and out are not storage qualifiers. Use varying instead.

// Same in vertex and fragment shader.
varying vec4 ourColor;

Alternatively, use a newer GLSL version.

#version 330
out vec4 ourColor;
in vec3 position;

#version 330
in vec4 ourColor;
out vec4 fragColor;