3

After following a set of OpenGL tutorials which were great but didn't let me understand the basics, I'm trying some very basic OpenGL coding with C++. My program is supposed to read a vertex and fragment shader and draw a triangle.

I get an error when linking the shaders (I suspect the error can be tracked down to the compiling of the shader though). I know my shaders are read by my program, but any changes to them doesn't affect my error. By running:

glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success); 

I receive the error: "Link called without any attached shader object". The programs builds, and my triangle shows, but is not affected by the shaders.

UPDATE

I no longer get the above error after fixing a mistake. I now get a complain after glCompileShader():

"Error: 0:3 'location' : syntax error parse error"

So I imagine it has to do with my shader files (will add them below). The shader files are taken from a tutorial, so I assumed they would work.

Shader files:

Vertex shader:

#version 330 layout (location = 0) in vec3 Position; void main() { gl_Position = vec4(0.5*Position.x, 0.5*Position.y, Position.z, 1.0); } 

Fragment shader:

#version 330 out vec4 FragColor; void main() { FragColor = vec4(1.0, 0.0, 0.0, 1.0); } 

In my main function i run:

compileShader(); 

Attach shaders:

static void AddShader(GLuint ShaderProgram, GLenum ShaderType, std::string filePath){ //create shader object GLuint ShaderObj = glCreateShader(ShaderType); //error if no shader if (ShaderObj == 0){ fprintf(stderr, "Error creating shader type %d\n", ShaderType); exit(0); } //"specify source code" //readShaderFile returns the shader file as a string std::string shaderFile = readShaderFile(filePath); const char* shaderFilePointer = shaderFile.c_str(); GLint ShaderFileLength[1]; ShaderFileLength[0] = strlen(shaderFilePointer); glShaderSource(ShaderObj, 1, &shaderFilePointer, ShaderFileLength); //compile the shader glCompileShader(ShaderObj); //check if compile successful GLint success; glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success); if (!success){ GLchar InfoLog[1024]; glGetShaderInfoLog(ShaderObj, sizeof(InfoLog), NULL, InfoLog); fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog); exit(1); } glAttachShader(ShaderProgram, ShaderObj); } 

And here are the functions used:

static void compileShaders(){ //create program GLuint ShaderProgram = glCreateProgram(); //check error if (ShaderProgram == 0){ fprintf(stderr, "Error creating shader program!\n"); exit(1); } //attach compiled shaders std::string vertexShaderFilePath = "Shaders/colShading.vert"; std::string fragShaderFilePath = "Shaders/colShading.frag"; AddShader(ShaderProgram, GL_VERTEX_SHADER, vertexShaderFilePath); AddShader(ShaderProgram, GL_FRAGMENT_SHADER, fragShaderFilePath); GLint Success = 0; GLchar ErrorLog[1024] = { 0 }; //link shader to program glLinkProgram(ShaderProgram); //check link error glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success); if (Success == 0) { glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog); fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog); } //use the linked shader program glUseProgram(ShaderProgram); } 

I doubt more of the code is needed to find the problem here, but just let me know. Thanks a lot in advance!

SOLUTION

The first answer below did the trick. I removed:

layout (location = 0) 

from the vertex shader and then added:

glBindAttribLocation(ShaderProgram, 0, "Position"); 

before the linking.

6
  • Do you have any attributes that you'd need to call glBindAttribLocation for? Commented Jul 16, 2015 at 22:08
  • No, the shader files are very simple and if understood correctly it is not needed. And more importantly, that I forgot to mention; any changes to my shader files doesn't affect anything. I still get the same error. Commented Jul 16, 2015 at 22:15
  • 1
    Could you post your shaders? Commented Jul 16, 2015 at 22:28
  • 2
    Have you tried changing the if (ShaderObj = 0){ line to use comparison (==) instead of assignment (=)? It is possible it is then reassigning ShaderObj to be always 0, which possibly does not exist, or has the wrong type. Commented Jul 17, 2015 at 0:19
  • Wow, that was bad mistake of me. I don't know how I missed it. But after fixing it, it still didn't run properly, so will check that and update the question. Thanks @SebastianMendez Commented Jul 17, 2015 at 6:19

1 Answer 1

4

It seems that either your hardware or your driver doesn't support the explicit shader location syntax, which require OpenGL/GLSL > 3.3.

To solve this, if samgak's answer doesn't help, you still have two options:

  1. Explicitly set the locations before linking the shader:

This is done with the glBindAttribLocation function, and means basically the same as what you have in your shader. Example:

AddShader(ShaderProgram, GL_VERTEX_SHADER, vertexShaderFilePath); AddShader(ShaderProgram, GL_FRAGMENT_SHADER, fragShaderFilePath); //... //Define the location of the attributes glBindAttribute(ShaderProgram, 0, "Position") //Bind "in Position" to location 0 //link shader to program glLinkProgram(ShaderProgram); 
  1. After linking, and while building your VAOs (or drawing the geometry), query the location of the attributes, and set the buffers accordingly:

You do this with the glGetAttribLocation function.

GLuint positionLoc = glGetAttribLocation(ShaderProgram, "Position");// Ask for the location of the attribute "Position //Create buffers and transfer data... glBindBuffer(gl.ARRAY_BUFFER, ...); glBufferData(...); //Turns on the vertex attribute for "Position" glEnableVertexAttribArray(positionLoc); //Set the pointer between buffer and attribute glVertexAttribPointer(positionLoc,...); 

For performance reasons, the first option is recommended, as it doesn't force a flush.

Sign up to request clarification or add additional context in comments.

11 Comments

Thank you! I removed: "layout (location = 0)" from the vertex shader and just added glBindAttribute(...) before the linking, and it worked perfectly. Love this forum, always great help!
Or actually what did I do now? by removing "layout (location=0)" it works properly also without using glBindAttribLocation(...).
upvoted, however I still don't think we've gotten to the bottom of this: why doesn't it work when specifying an attibute index is supposed to be supported in version 3.3+?
@remi000: If you don't use glBindAttribLocation, the driver assigns a location number arbitrarily. In your case, it so happens to also be 0, so your program works. However, it wouldn't be wise to rely on this always being the case. The driver could for some reason assign 1 as the location, and you would have the wrong data in your shader.
@samgak It's working well now, and I'm not even sure what the "location = 0 " was doing in the first place, as I'm quite new to this. But how was this supposed to work actually?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.