Reputation: 51
I am creating a simple OpenGL ES 2.0 application for iOS, and whenever I call glDrawArrays. I found that this was occurring when I had previously called glEnableVertexAttribArray for my two attributes (position and color), and then found that glGetAttribLocation was returning 1 for position, and 0 for color, and then also found that glGetUniformLocation was returning 0 for my MVP matrix. I am not sure if 0 is a valid value, or why glEnableVertexAttribArray appears to be causing EXC_BAD_ACCESS when glDrawArrays is called.
Here is my code:
compileShaders function:
-(void)compileShaders {
GLuint vertShader = [self compileShader:@"Shader" ofType:GL_VERTEX_SHADER];
GLuint fragShader = [self compileShader:@"Shader" ofType:GL_FRAGMENT_SHADER];
GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
GLchar messages[256];
glGetProgramInfoLog(program, sizeof(messages), 0, &messages[0]);
NSLog(@"%@", [NSString stringWithUTF8String:messages]);
exit(1);
}
glUseProgram(program);
_positionSlot = glGetAttribLocation(program, "position");
_colorSlot = glGetAttribLocation(program, "color"); //Returns 0
_mvpSlot = glGetUniformLocation(program, "MVP"); //Returns 0
if (!_positionSlot || !_colorSlot || !_mvpSlot) {
NSLog(@"Failed to retrieve the locations of the shader variables:\n Position:%i\n Color:%i\n MVP:%i", _positionSlot, _colorSlot, _mvpSlot); //Prints out the values of 1, 0, 0
}
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
My render function:
-(void)render:(CADisplayLink *)displayLink {
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
GLfloat mvp[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
glUniformMatrix4fv(_mvpSlot, 1, 0, mvp);
glViewport(0, 0, width, height);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(_colorSlot, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
And my vertex shader:
attribute vec4 position;
attribute vec4 color;
uniform mat4 MVP;
varying vec4 v_color;
void main(void) {
gl_Position = MVP * position;
v_color = color;
}
Upvotes: 5
Views: 13487
Reputation: 121
I have the same issue and no solution, however I have tried to extensively debug, so I thought perhaps it might be helpful to share.
I traced the issue down to glCreateProgram()
and glCreateShader()
calls. They both return zero, which is the error return. However in both cases glGetError()
returns GL_NO_ERROR
. In fact no error pops up all the way through the compile and link chain following the create calls.
I have the same symptom that glGetAttribLocation
and also uniforms always return zero (rather than -1 for error!). But I can even feed broken shader files and it will not lead to a compile error or any log info. The correct string was checked to be fed into to compile.
I am completely dumbfounded by the behavior, because clearly glCreateProgram
errors but doesn't set an error. And it is not clear to me at all why it does error. What is especially confusion is that a whole chain of GL function calls don't return errors. I am getting my first error when I the program calls a gl function that operates on a uniform, such as glUniformMatrix4fv()
or glUniform1i()
. But clearly things are broken way before then, because all uniforms return as 0 even though they cannot all be zero.
Edit: I found the solution in my case. Opengles1 seems to be quite flexible when framebuffers are set up. But I needed to force framebuffer setup before starting with shaders to get rid of the issue. e.g. if one follows the old eaglview template, framebuffers are created in layoutSubviews
, however that is too late for a typical initialization of shaders in say initwithcoder
. The symptoms are the above otherwise.
Upvotes: 2
Reputation: 56347
0 is a valid value, -1 is the "error" or "not found" value. The space for uniform locations and attrib locations is separate, so it's fine to have both a location 0 uniform and a location 0 attribute.
You should post the vertices and colors arrays to check if they have the right sizes, this is likely to cause a crash.
Upvotes: 8