I am trying to create a GLSL example on Mac. I am trying to set up one color attribute per vertex. However, when the program runs, I just get a purple screen (the purple comes from glClearColor). I post the relevant code snippets.
-(void)drawRect:(NSRect)dirtyRect
{
// get program ID for shader program
GLuint programID = [self loadShaders];
// get new dimensions
NSSize dim = [self frame].size;
// clear the background with color
glClearColor(0.4f, 0.1f, 0.7f, 1.0f);
glDepthRange(1.0, -1.0);
glViewport(0, 0, dim.width, dim.height);
glClear(GL_COLOR_BUFFER_BIT);
// generate a buffer for our triangle
glGenBuffers(2, vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glUseProgram(programID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(VERTEX_POS_INDEX, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, VERTEX_POS_SIZE*sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(VERTEX_COLOR_INDEX, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, VERTEX_POS_SIZE*sizeof(colors), colors);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glUseProgram(0);
// flush buffer
glFlush();
[[self openGLContext] flushBuffer];
}
And then the loading shadings code:
-(GLuint)loadShaders
{
printf("GLSL version %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
printf("GL Version: %s", glGetString(GL_VERSION));
// Create the shaders
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// get handle for app bundle
NSBundle *appBundle = [NSBundle mainBundle];
// get the path for the vertex shader file
NSString *vertexFilePath = [appBundle pathForResource:vertexShaderFile ofType:nil];
// get the path for the fragment shader file
NSString *fragmentFilePath = [appBundle pathForResource:fragmentShaderFile ofType:nil];
// get the contents of the vertex shader file into a string
NSString *vertexFileContents = [NSString stringWithContentsOfFile:vertexFilePath encoding:NSUTF8StringEncoding error:NULL];
NSLog(@"%@", vertexFileContents);
// get the contents of the fragment shader file into a string
NSString *fragmentFileContents = [NSString stringWithContentsOfFile:fragmentFilePath encoding:NSUTF8StringEncoding error:NULL];
NSLog(@"%@", fragmentFileContents);
GLint Result = GL_FALSE;
int infoLogLength;
// get a pointer the vertex shader program source, compile shader program
const char *vertexSourcePointer = [vertexFileContents UTF8String];
glShaderSource(vertexShaderID, 1, &vertexSourcePointer, NULL);
glCompileShader(vertexShaderID);
// check the vertex shader
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
char vertexShaderErrorMessage[infoLogLength];
glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, vertexShaderErrorMessage);
// print error message
NSLog(@"%@", [NSString stringWithUTF8String:vertexShaderErrorMessage]);
// get a pointer to the fragment shader program source, compile shader program
const char *fragmentSourcePointer = [fragmentFileContents UTF8String];
glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer, NULL);
glCompileShader(fragmentShaderID);
// check the fragment shader
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
char fragmentShaderErrorMessage[infoLogLength];
glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, fragmentShaderErrorMessage);
// print error message
NSLog(@"%@", [NSString stringWithUTF8String:fragmentShaderErrorMessage]);
// link the program
NSLog(@"Linking program...");
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glBindAttribLocation(programID, 0, "position");
glBindAttribLocation(programID, 1, "inColor");
glLinkProgram(programID);
// check the program
glGetProgramiv(programID, GL_LINK_STATUS, &Result);
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
char shaderProgramErrorMessage[max(infoLogLength, (int)1)];
glGetProgramInfoLog(programID, infoLogLength, NULL, shaderProgramErrorMessage);
// pring error message
NSLog(@"%@", [NSString stringWithUTF8String:shaderProgramErrorMessage]);
// delete shaders
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
return programID;
}
And finally the shaders:
#version 120
attribute vec4 position;
attribute vec4 inColor;
varying vec4 outColor;
void main()
{
gl_Position = position;
outColor = inColor;
}
And
#version 120
varying vec4 outColor;
void main()
{
gl_FragColor = outColor;
}
Looks fairly good, though I do see one mistake.
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(VERTEX_POS_INDEX,
VERTEX_POS_SIZE,
GL_FLOAT,
GL_FALSE,
VERTEX_POS_SIZE*sizeof(vertices),
vertices);
If you are using VBO, then the final attribute to glVertexAttribPointer should be the offset from the start of the currently bound buffer.
If you were using vertex arrays (no glBindBuffer), then you would point to vertices with the final argument of glVertexAttribPointer.
However, since you've already uploaded vertices
to a buffer and bound it, the final value of glVertexAttribPointer should be the offset from the start of the vertices buffer, which in your case, should be 0
.
Same mistake for the colors buffer as well.