Reputation: 157
Before I post some code, I'll explain: I'm learning OpenGL ES 2.0 on the iPhone platform right now, and I've got my program to compile every time, but it only runs correctly some of the time. It's a super-simple program with a vertex shader and a fragment shader and a single triangle.
For some reason, only certain attribute names in the vertex shader work. For instance, if I use attribute vec4 v_Color
the program runs just fine, but if I use attribute vec4 v_color
without the capital "C", it reassigns my position attributes to be my color attributes and vice versa, even though I explicitly make the glBindAttribLocation()
name parameter match exactly with the attribute name. Another one that doesn't work is vColor
but for some reason a_color
works just fine. I tried using some random word like "bar" and that didn't work. Keep in mind, I'm matching up the name from the vertex shader with the name I specify in glBindAttribLocation()
.
It seems unlikely that only certain names should work. (Isn't the whole point of generic attributes to give the programmer more flexibility?) Given that all I do is change the names, I'm wondering if there's something wonky with the way I'm reading the vertex shader into my program in the first place; maybe I'm using the wrong type of encoding. Maybe it misreads it and tries to figure it out on its own, thus ignoring the explicit names I have it and reassigning them.
Here's the code I'm using to read the vertex shader:
NSError *error;
NSString *vertPath = [[NSBundle mainBundle] pathForResource:@"Simple" ofType:@"vert"];
NSString *vertShaderString = [NSString stringWithContentsOfFile:vertPath encoding:NSUTF8StringEncoding error:&error];
const GLchar *vertShaderText = [vertShaderString UTF8String];
if (!vertShaderString) {
NSLog(@"%@", [error localizedDescription]);
}
vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &vertShaderText, NULL);
glCompileShader(vertShader);
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &vertCompiled);
if (!vertCompiled) {
NSLog(@"Vert shader not compiled.");
}
glAttachShader(prog, vertShader);
Then the code I'm actually using to make my draw call:
GLfloat vertices[] = { 0.0, 0.0, 0.0, 0.5, 0.5, 0.5 };
GLubyte indices[3] = { 0, 1, 2 };
// Position vertex attribute data
glEnableVertexAttribArray(0);
glBindAttribLocation(prog, 0, "a_position");
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
// Color vertex attribute data
GLfloat vColors[] = {
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0 };
glEnableVertexAttribArray(1);
glBindAttribLocation(prog, 1, "a_color");
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, vColors);
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(GLubyte), GL_UNSIGNED_BYTE, indices);
Finally, the rather trivial vertex shader (no need to include the frag shader because it's so basic):
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 varColor;
void main() {
gl_Position = a_position;
varColor = a_color;
}
The above code actually works just fine, but if I were to change a_color
to v_color
, it would suddenly switch my position data and my color data, so my triangle changes shape and the color is all wrong, which is of course undesirable. It's a very odd problem. Do you suspect this is a problem with my Objective-C implementation or with my OpenGL ES 2.0 implementation?
Thanks for your time!
Upvotes: 3
Views: 1207
Reputation: 35933
Calling glBindAttribLocation
only takes effect the next time the program is linked with glLinkProgram
. Calling it as you do here does nothing, and as such your variables get assigned to whatever random number the compiler comes up with.
Another option, if you don't want to call it before linking, than use glGetAttribLocation
here instead to query the value that OpenGL has assigned for each attribute. Though try to cache the value so that you're not calling get
on every frame.
Upvotes: 4