0

I'm trying to create a shader that has a vertex, geometry, and fragment shader. I started off by just having a vertex and fragment shader and things worked fine but as soon as I try to attach my geometry shader as well the link is no longer successful.

Here is my geometry shader code:

//Create geometry shader for exploding
const GLchar* geometryShader =
    "#version 410\n " \
    "layout (triangles) in;" \
    "layout (triangle_strip, max_vertices = 3) out;" \
    "in VS_OUT {" \
    "vec2 texCoords;" \
    "} gs_in[];" \
    "out vec2 TexCoords; " \
    "uniform float time;" \
    "vec4 explode(vec4 position, vec3 normal)" \
    "{" \
    "float magnitude = 2.0;" \
    "vec3 direction = normal * ((sin(time) + 1.0) / 2.0) * magnitude; " \
    "return position + vec4(direction, 0.0);" \
    "}" \
    "vec3 GetNormal()" \
    "{" \
    "vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);" \
    "vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);" \
    "return normalize(cross(a, b));" \
    "}" \
    "void main() { " \
    "vec3 normal = GetNormal();" \
    "gl_Position = explode(gl_in[0].gl_Position, normal);" \
    "TexCoords = gs_in[0].texCoords;" \
    "EmitVertex();" \
    "gl_Position = explode(gl_in[1].gl_Position, normal);" \
    "TexCoords = gs_in[1].texCoords;" \
    "EmitVertex();" \
    "gl_Position = explode(gl_in[2].gl_Position, normal);" \
    "TexCoords = gs_in[2].texCoords;" \
    "EmitVertex();" \
    "EndPrimitive();" \
    "}" \
    "" \
    "" \
    "" \
    "";

And the code for loading my shaders:

GLuint LoadShader(const GLchar* vert, const GLchar* geo, const GLchar* frag)
{
    //Create a new vertex shader, attach source code, compile it and check for errors
    GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vert, NULL);
    glCompileShader(vertexShaderId);
    GLint success = 0;
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &success);
    //Display any errors that occur in the vertex shader
    if (!success)
    {
        GLint maxLength = 0;
        glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(vertexShaderId, maxLength, &maxLength, &errorLog.at(0));
        std::cout << &errorLog.at(0) << std::endl;
        throw std::exception();
    }
    //Create a new geometry shader, attach source code, compile it and check for errors
    GLuint geometryShaderId = glCreateShader(GL_GEOMETRY_SHADER);
    glShaderSource(geometryShaderId, 1, &geo, NULL);
    glCompileShader(geometryShaderId);
    glGetShaderiv(geometryShaderId, GL_COMPILE_STATUS, &success);
    //Display any errors that occur in the vertex shader
    if (!success)
    {
        GLint maxLength = 0;
        glGetShaderiv(geometryShaderId, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(geometryShaderId, maxLength, &maxLength, &errorLog.at(0));
        std::cout << &errorLog.at(0) << std::endl;
        throw std::exception();
    }
    //Create a new fragment shader, attach source code, compile it and check for errors
    GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &frag, NULL);
    glCompileShader(fragmentShaderId);
    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &success);
    //Display any errors that occur in the fragment shader
    if (!success)
    {
        GLint maxLength = 0;
        glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(fragmentShaderId, maxLength, &maxLength, &errorLog.at(0));
        std::cout << &errorLog.at(0) << std::endl;
        throw std::exception();
    }
    //Create new shader program and attach our shader objects
    GLuint programId = glCreateProgram();
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, geometryShaderId);
    glAttachShader(programId, fragmentShaderId);
    //Ensure the VAO "position" attribute stream gets set as the first position during the link.
    glBindAttribLocation(programId, 0, "a_Position");
    glBindAttribLocation(programId, 1, "a_Texcord");
    glBindAttribLocation(programId, 2, "in_Normal");
    //Perform the link and check for failure
    glLinkProgram(programId);
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if (!success)
    {
        throw std::exception();
    }
    //Detach and destroy the shader objects. These are no longer needed because we now have a complete shader program
    glDetachShader(programId, vertexShaderId);
    glDeleteShader(vertexShaderId);
    glDetachShader(programId, geometryShaderId);
    glDeleteShader(geometryShaderId);
    glDetachShader(programId, fragmentShaderId);
    glDeleteShader(fragmentShaderId);
    //Find uniform locations
    GLint colorloc = glGetUniformLocation(programId, "u_Texcord");
    GLint modelLoc = glGetUniformLocation(programId, "u_Model");
    GLint viewLoc = glGetUniformLocation(programId, "u_View");
    GLint projectionLoc = glGetUniformLocation(programId, "u_Projection");
    if (modelLoc == -1)
    {
        throw std::exception();
    }
    if (projectionLoc == -1)
    {
        throw std::exception();
    }
    return programId;
}

An exception is being thrown at this part (and if I comment out this part it gets caught on the other two exceptions but I assume this is because the link was not successful although I could be wrong):

    //Perform the link and check for failure
    glLinkProgram(programId);
    glGetProgramiv(programId, GL_LINK_STATUS, &success);
    if (!success)
    {
        throw std::exception();
    }

I've looked online about why this could be happening at there is a whole list of reasons but as this doesn't display an error message I'm not quite sure what is going wrong. Any advice would be greatly appreciated and thanks in advance!

  • 4
    "I've looked online about why this could be happening at there is a whole list of reasons " And therefore, the GL has a program info log where the linker will store error messages and warnings, "but as this doesn't display an error message". That's because you never query the program info log, you only query the info logs of the shader objects. – derhass Apr 17 '21 at 20:22
  • and please use files for your shaders, its more clean, less typing and you can see your errors more clearer – vikAy Apr 17 '21 at 20:56
  • I didn't even know you could have them in different files lol I'm justing using the basics I was taught so far. And if you could give any advice on querying the program info log I would be very grateful thank you – samuel robinson Apr 17 '21 at 22:09

0 Answers0