TheAmateurProgrammer
TheAmateurProgrammer

Reputation: 9392

Getting GLSL 1.5 to work on Mac OS X

I'm trying to create my own vertex and fragment shaders in my program (which is basically a very simple program that displays a triangle with VBO). However, when I try run it, I always get a black screen with nothing showing up. I've checked the compile log and it returns with no error. I have yet to run a program with my own custom shader which makes me wonder if I'm doing anything wrong here. I'm running my code on OpenGL 3.2 and GLSL 1.5

The following is the code that I'm trying to run currently


GLuint vbo;

GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

const char *vertexShader = "\n\
#version 150\n\
\n\
layout (location=0) in vec4 position;\n\
void main()\n\
{\n\
gl_Position = position;\n\
}\n\
";

const char *fragmentShader = "\n\
#version 150\n\
\n\
out vec4 outColor;\n\
\n\
void main()\n\
{\n\
    outColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
}";


- (void)drawRect:(NSRect)dirtyRect
{
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    glUseProgram(programId);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableClientState(GL_VERTEX_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, 0);

    glDrawArrays(GL_TRIANGLES, 0, sizeof(data));

    glFlush();


    glDisableClientState(GL_VERTEX_ARRAY);

}

-(void)reshape
{
    glViewport(0, 0, w, h);
    gluPerspective(45.0,                  //The camera angle
                   (double)w / (double)h, //The width-to-height ratio
                   1.0,                   //The near z clipping coordinate
                   200.0); 
}

-(void)prepareOpenGL
{
    glEnable(GL_DEPTH_TEST);  

    glGenBuffersARB(1, &vbo);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);


    vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderId, 1, &vertexShader, NULL);

    glCompileShader(vertexShaderId);

    GLint completed;
    glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &completed);

    if (!completed)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(vertexShaderId, length, &length, log);
        fprintf(stderr, "Vertex compile log = '%s'\n", log);
    }



    fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
    glCompileShader(fragmentShaderId);

    GLint complete;

    glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &complete);

    if (!complete)
    {
        GLint length;
        GLchar *log;
        glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &length);

        log = (GLchar *)malloc(length);
        glGetShaderInfoLog(fragmentShaderId, length, &length, log);
        fprintf(stderr, "fragment compile log = '%s'\n", log);
    }

    programId = glCreateProgram();

    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId, fragmentShaderId);

    glLinkProgram(programId);

    glUseProgram(programId);
}

Upvotes: 0

Views: 2092

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473174

There are several problems here. From top to bottom:


GLfloat data[] = {0.0, 0.0, -5.0,
                  1.0, 0.0, -5.0,
                  1.0, 1.0, -5.0
};

This data is not visible, because the Z value is outside of the viewing volume [-1, 1]. Try using 0.0 instead.


#version 150\n\
\n\
layout (location=0) in vec4 position;

layout(location=0) is only legal for vertex shader inputs in two circumstances:

  1. You are using GLSL version 3.30 or greater. Your shader says #version 150.
  2. You are using the ARB_explicit_attrib_location extension. In that case, you would need a #extension declaration to activate it in your shader. Plus, I know for a fact that OSX's GL 3.2 support does not provide this extension.

So you need to do it the old fashioned way: with glBindAttribLocation. Use this function before you link your program.


glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);

This is not only unnecessary, it's actively destructive to what you're trying to accomplish, since it like causes the generation of an OpenGL error when you attempt to render.

If you're using generic attributes, you don't need the old-style attributes.


glDrawArrays(GL_TRIANGLES, 0, sizeof(data));

sizeof(data) is the size in bytes of the data array. On most machines, that's going to be 36. You are not rendering 36 vertices; you are rendering three. So this should be:

glDrawArrays(GL_TRIANGLES, 0, 3);

gluPerspective(45.0,                  //The camera angle
               (double)w / (double)h, //The width-to-height ratio
               1.0,                   //The near z clipping coordinate
               200.0); 

This isn't a problem so much as completely pointless. You're rendering with shaders, and you're not using the built-in matrix stuff. This does nothing.


glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);

This is also likely not a "problem", but it could be. The functions and enumerators that end in "ARB" represent OpenGL extensions. So you're using the functions exposed by the ARB_vertex_buffer_object extension.

This extension has been core since GL 1.4. In fact, you're not even using the extension consistently (which is where a problem could arise). You're setting you the buffer's data with the ARB extension, but using the core functions when you render.

Just ditch the ARB extension stuff and use the core feature.


    log = (GLchar *)malloc(length);
    glGetShaderInfoLog(vertexShaderId, length, &length, log);
    fprintf(stderr, "Vertex compile log = '%s'\n", log);

This isn't going to cause a bug, but... where's your call to free?


glLinkProgram(programId);
glUseProgram(programId);

You should always check for errors after compiling a shader or linking a program.


Your code seems like it's been copy-and-pasted together from various sources, to form some kind of Frankenstein's Program. Most of your problem stem from different bits of code acting in different ways from how you plan on using them. You really should investigate how this stuff actually works; that way, you won't run into these problems.

Upvotes: 9

Related Questions