0
votes

I am trying to draw a very simple blue square with a red background in OpenGL using an NSOpenGL on Mountain Lion. The code is simple and should work, I'm assuming it's a problem with me setting up the context.

Here is my GLView interface:

#import <Cocoa/Cocoa.h>
#import <OpenGL/gl.h>
#import <GLKit/GLKit.h>

typedef struct {
    char *Name;
    GLint Location;
} Uniform;

@interface MyOpenGLView : NSOpenGLView {
    Uniform *_uniformArray;
    int _uniformArraySize;
    GLKMatrix4 _projectionMatrix;
    GLKMatrix4 _modelViewMatrix;
    IBOutlet NSWindow *window;
    int height, width;
}

-(void)drawRect:(NSRect)bounds;

@end

The implementation:

GLfloat square[] = {
    -0.5, -0.5,
    0.5, -0.5,
    -0.5, 0.5,
    0.5, 0.5
};

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}

-(void)awakeFromNib {
    NSString *vertexShaderSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"VertexShader" ofType:@"vsh"] encoding:NSUTF8StringEncoding error:nil];

    const char *vertexShaderSourceCString = [vertexShaderSource cStringUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"%s",vertexShaderSourceCString);

    NSString *fragmentShaderSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"FragmentShader" ofType:@"fsh"] encoding:NSUTF8StringEncoding error:nil];
    const char *fragmentShaderSourceCString = [fragmentShaderSource cStringUsingEncoding:NSUTF8StringEncoding];

    NSLog(@"%s",fragmentShaderSourceCString);

    NSOpenGLContext *glContext = [self openGLContext];
    [glContext makeCurrentContext];

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

    GLint compileSuccess;
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
        GLint logLength;
        glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
        if(logLength > 0) {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetShaderInfoLog(fragmentShader, logLength, &logLength, log);
            NSLog(@"Shader compile log:\n%s", log);
            free(log);
        }
        exit(1);
    }

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSourceCString, NULL);
    glCompileShader(vertexShader);

    GLuint program = glCreateProgram();
    glAttachShader(program, fragmentShader);
    glAttachShader(program, vertexShader);
    glLinkProgram(program);

    glUseProgram(program);

    const char *aPositionCString = [@"a_position" cStringUsingEncoding:NSUTF8StringEncoding];
    GLuint aPosition = glGetAttribLocation(program, aPositionCString);

    glVertexAttribPointer(aPosition, 2, GL_FLOAT, GL_FALSE, 0, square);
    glEnable(aPosition);

    GLint maxUniformLength;
    GLint numberOfUniforms;
    char *uniformName;

    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numberOfUniforms);
    glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLength);

    _uniformArray = malloc(numberOfUniforms * sizeof(Uniform));
    _uniformArraySize = numberOfUniforms;

    for (int i =0; i <numberOfUniforms; i++) {
        GLint size;
        GLenum type;
        GLint location;

        uniformName = malloc(sizeof(char*)*maxUniformLength);
        glGetActiveUniform(program, i, maxUniformLength, NULL, &size, &type, uniformName);
        _uniformArray[i].Name = uniformName;
        location = glGetUniformLocation(program, uniformName);
        _uniformArray[i].Location = location;
    }

    _modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f);
    _projectionMatrix = GLKMatrix4MakeOrtho(-1, 1, -1.5, 1.5, -1, 1);
}

- (void)drawRect:(NSRect)bounds {
    glClearColor(1.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    glViewport(0, 0, 480, 360);

    for (int i = 0; i <_uniformArraySize; i++) {
        if (strcmp(_uniformArray[i].Name, "ModelViewProjectionMatrix")==0) {
            // Multiply the transformation matrices together
            GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(_projectionMatrix,        _modelViewMatrix);
            glUniformMatrix4fv(_uniformArray[i].Location, 1, GL_FALSE,           modelViewProjectionMatrix.m);
        }
    }
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glFlush();
}

My very simple fragment shader:

void main() {
    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}

simple vertex shader:

attribute vec4 a_position;

uniform mat4 ModelViewProjectionMatrix;

void main() {
    gl_Position = a_position * ModelViewProjectionMatrix;
}

I get no compilation errors, just a red screen and no blue square. Could someone please help me figure out what's wrong. I do get a warning though, stating Gl.h and gl3.h are both included. I'd like to be using OpenGL 2

1

1 Answers

0
votes

Where is your view matrix (AKA your look-at matrix)? For my NSOpenGLView, I have at least three matrices, the model view (which consists of the multiplicative result of the rotation and translation matrices), the projection matrix (which takes into account your frustum scale, aspect ratio, near plane, and far plane), and the view matrix (which takes into account the viewers eye position in the "world", the point of focus, and the direction of the up vector). I will say big ups on placing the code in the awakeFromNib, taught me something...