OpenGL ES 2: Obj-C Vertices -> Shader

Discussion in 'iOS Programming' started by Blakeasd, May 21, 2013.

  1. Blakeasd macrumors 6502a

    Joined:
    Dec 29, 2009
    #1
    Hello. I am attempting to learn OpenGL ES 2 with this tutorial. I am having a hard time figuring out when the defined Vertices[] in Objective-C is being passed along to the shaders. Here is my code so far:

    Code:
    #import "OpenGLView.h"
    
    @implementation OpenGLView
    
    typedef struct{
        float Position[3];
        float Color[4];
    }
    Vertex;
    
    const Vertex Vertices[] = {
        {{1, -1, 0}, {1, 0, 0, 1}},
        {{1, 1, 0}, {0, 1, 0, 1}},
        {{-1, 1, 0}, {0, 0, 1, 1}},
        {{-1, -1, 0}, {0, 0, 0, 1}}};
    
    const GLubyte Indices[] = {
        0,1,2,
        2,3,0
    };
    
    
    - (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {
        
        // 1
        NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName
                                                               ofType:@"glsl"];
        NSError* error;
        NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath
                                                           encoding:NSUTF8StringEncoding error:&error];
        if (!shaderString) {
            NSLog(@"Error loading shader: %@", error.localizedDescription);
            exit(1);
        }
        
        // 2
        GLuint shaderHandle = glCreateShader(shaderType);
        
        // 3
        const char * shaderStringUTF8 = [shaderString UTF8String];
        int shaderStringLength = [shaderString length];
        glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
        
        // 4
        glCompileShader(shaderHandle);
        
        // 5
        GLint compileSuccess;
        glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
        if (compileSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
            NSString *messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"%@", messageString);
            exit(1);
        }
        
        return shaderHandle;
        
    }
    
    - (void)compileShaders {
        
        // 1
        GLuint vertexShader = [self compileShader:@"SimpleVertex"
                                         withType:GL_VERTEX_SHADER];
        GLuint fragmentShader = [self compileShader:@"SimpleFragmentShader"
                                           withType:GL_FRAGMENT_SHADER];
        
        // 2
        GLuint programHandle = glCreateProgram();
        glAttachShader(programHandle, vertexShader);
        glAttachShader(programHandle, fragmentShader);
        glLinkProgram(programHandle);
        
        // 3
        GLint linkSuccess;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
        if (linkSuccess == GL_FALSE) {
            GLchar messages[256];
            glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
            NSString *messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"%@", messageString);
            exit(1);
        }
        
        // 4
        glUseProgram(programHandle);
        
        // 5
        _positionSlot = glGetAttribLocation(programHandle, "Position");
        _colorSlot = glGetAttribLocation(programHandle, "SourceColor");
        glEnableVertexAttribArray(_positionSlot);
        glEnableVertexAttribArray(_colorSlot);
    }
    
    -(GLuint)setupVBOs{
        GLuint vertexBuffer;
        glGenBuffers(1, &vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
        
        GLuint indexBuffer;
        glGenBuffers(1, &indexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
        
        
        
    }
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self setupLayer];
            [self setupContext];
            [self setupRenderBuffer];
            [self setupFrameBuffer];
            [self compileShaders];
            [self setupVBOs];
            [self render];
        }
        return self;
    }
    
    +(Class)layerClass{
    
        return [CAEAGLLayer class];
    }
    
    - (void)setupLayer {
        _eaglLayer = (CAEAGLLayer*) self.layer;
        _eaglLayer.opaque = YES;
    }
    
    
    - (void)setupContext {
        EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
        _context = [[EAGLContext alloc] initWithAPI:api];
        if (!_context) {
            NSLog(@"Failed to initialize OpenGLES 2.0 context");
            exit(1);
        }
        
        if (![EAGLContext setCurrentContext:_context]) {
            NSLog(@"Failed to set current OpenGL context");
            exit(1);
        }
    }
    
    -(void)setupRenderBuffer{
        glGenRenderbuffers(1, &_colorRenderBuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
        [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
    }
    
    -(void)setupFrameBuffer{
        GLuint frameBuffer;
        glGenFramebuffers(1, &frameBuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
    
    }
    
    -(void)render{
        glClearColor(0, 104.0/255.0, 55.0/255.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
    
        glViewport(0, 0, self.frame.size.width, self.frame.size.height);
        
      
        
        glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),0);
        
        glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE,
                              sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
        
      
        
        glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
        
        [_context presentRenderbuffer:GL_RENDERBUFFER];
        
    }
    
    
    @end
    
    This code is a simple OpenGLView (subclass of UIView w/CAEAGLLayer). A rainbow effect is drawn onto the screen. Can someone point out in the code where the definite line is where Objective-C gives the Vertices off to the shaders. I could probably back track if I had the line that says "Hey shaders, here are the Vertices and Indices". I would even like it if someone could just show me a flow-chart type thing (this --> this) of the roadmap from Objc to the shaders -- Not the Cocoa stuff, just gl.

    Thanks!!
     
  2. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #2
    It looks like it happens in the glBufferData() calls in your setupVBOs method.
     
  3. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #3
    How does this come into play with _positionSlot and _colorSlot?

    Thanks
     
  4. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #4
    It looks like your glGetAttribLocation() and glVertexAttribPointer() calls tell the shader where to find the Position and SourceColor attributes in your Vertices array.
     
  5. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #5
    Ahh... I get it now. I wish the OpenGL ES 2 API was easier to work with :S

    Thanks for All of Your Help!
     

Share This Page