Bare bones openGL in openFrameworks
During our last openFrameworks freakDay meeting we discussed the usage of VBOs, vertex attributes and shaders in openFrameworks. To explain the openGL concepts I created a demo application and shader which shows how to use openGL only without the need of ofShader, ofVBO.

// Error.h /* ** error.h ** ** Copyright (c) 2008 Max Rupp (feelgood@cs.pdx.edu) All rights reserved. */ #ifndef __ERROR_H__ #define __ERROR_H__ #define DEBUG #ifdef DEBUG #include <stdlib.h> #include <assert.h> /* #define eglGetError( )\ {\ for ( GLenum Error = glGetError( ); ( GL_NO_ERROR != Error ); Error = glGetError( ) )\ {\ switch ( Error )\ {\ case GL_INVALID_ENUM: printf( "\n%s\n\n", "GL_INVALID_ENUM" ); assert( 0 ); break;\ case GL_INVALID_VALUE: printf( "\n%s\n\n", "GL_INVALID_VALUE" ); assert( 0 ); break;\ case GL_INVALID_OPERATION: printf( "\n%s\n\n", "GL_INVALID_OPERATION" ); assert( 0 ); break;\ case GL_STACK_OVERFLOW: printf( "\n%s\n\n", "GL_STACK_OVERFLOW" ); assert( 0 ); break;\ case GL_STACK_UNDERFLOW: printf( "\n%s\n\n", "GL_STACK_UNDERFLOW" ); assert( 0 ); break;\ case GL_OUT_OF_MEMORY: printf( "\n%s\n\n", "GL_OUT_OF_MEMORY" ); assert( 0 ); break;\ default: break;\ }\ }\ } */ #define eglGetError() #define eglCheckFramebufferStatus( )\ {\ switch ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) )\ {\ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: printf( "\n%s\n\n", "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: printf( "\n%s\n\n", "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: printf( "\n%s\n\n", "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: printf( "\n%s\n\n", "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_UNSUPPORTED: printf( "\n%s\n\n", "GL_FRAMEBUFFER_UNSUPPORTED" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: printf( "\n%s\n\n", "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" ); assert( 0 ); break;\ case GL_FRAMEBUFFER_UNDEFINED: printf( "\n%s\n\n", "GL_FRAMEBUFFER_UNDEFINED" ); assert( 0 ); break;\ default: break;\ }\ } #define eglGetShaderInfoLog( Shader )\ {\ GLint Status, Count;\ GLchar *Error;\ \ glGetShaderiv( Shader, GL_COMPILE_STATUS, &Status );\ \ if ( !Status )\ {\ glGetShaderiv( Shader, GL_INFO_LOG_LENGTH, &Count );\ \ if ( Count > 0 )\ {\ Error = (GLchar *)malloc(Count);\ glGetShaderInfoLog( Shader, Count, NULL, Error );\ \ printf( "%s\n", Error );\ \ free( Error );\ \ assert( 0 );\ }\ }\ } #else #define eglGetError( ) #define eglCheckFramebufferStatus( ) #define eglGetShaderInfoLog( Shader ) #endif /* DEBUG */ #endif /* __ERROR_H__ */
// testApp.h #pragma once #include "ofMain.h" #include "Error.h" class testApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed (int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); // shader GLuint shader_vertex; GLuint shader_fragment; GLuint prog; GLint pos_attrib; GLint col_attrib; GLint custom_attrib; // vbo GLuint buffer; string readFile(string file); };
// testApp.cpp #include "testApp.h" #include <stdlib.h> #include <fstream> struct VertexData { ofVec3f pos; ofVec3f col; float custom; }; //-------------------------------------------------------------- void testApp::setup(){ ofBackground(33); // Compile and link shaders into a program. shader_vertex = glCreateShader(GL_VERTEX_SHADER); eglGetError(); shader_fragment = glCreateShader(GL_FRAGMENT_SHADER); eglGetError(); string vert_source = readFile("program.vert"); string frag_source = readFile("program.frag"); const char* vert_ptr = vert_source.c_str(); const char* frag_ptr = frag_source.c_str(); glShaderSource(shader_vertex, 1, &vert_ptr, NULL); eglGetError(); glShaderSource(shader_fragment, 1, &frag_ptr, NULL); eglGetError(); glCompileShader(shader_vertex); eglGetError(); glCompileShader(shader_fragment); eglGetError(); prog = glCreateProgram(); eglGetError(); glAttachShader(prog, shader_vertex); eglGetError(); glAttachShader(prog, shader_fragment); eglGetError(); glLinkProgram(prog); eglGetError(); glUseProgram(prog); eglGetError(); // create buffer float s = 4; VertexData points[4]; points[0].pos.set(-s, s, 0); points[1].pos.set(s,s, 0); points[2].pos.set(s,-s,0); points[3].pos.set(-s, -s, 0); points[0].col.set(1,0,0); points[1].col.set(0,1,0); points[2].col.set(0,0,1); points[3].col.set(1,0,1); points[0].custom = 0.5; points[1].custom = 1.0; points[2].custom = 1.0; points[3].custom = 0.8; glGenBuffers(1, &buffer); eglGetError(); glBindBuffer(GL_ARRAY_BUFFER, buffer); eglGetError(); glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData)* 4, &points[0].pos.x, GL_DYNAMIC_DRAW); eglGetError(); // enable vertex attributes. pos_attrib = glGetAttribLocation(prog, "pos"); eglGetError(); col_attrib = glGetAttribLocation(prog, "col"); eglGetError(); custom_attrib = glGetAttribLocation(prog, "custom"); eglGetError(); glEnableVertexAttribArray(pos_attrib); eglGetError(); glEnableVertexAttribArray(col_attrib); eglGetError(); glEnableVertexAttribArray(custom_attrib); eglGetError(); // where can opengl find the values in the buffer? glVertexAttribPointer(pos_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)offsetof(VertexData, pos)); eglGetError(); glVertexAttribPointer(col_attrib, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*) offsetof(VertexData, col)); eglGetError(); glVertexAttribPointer(custom_attrib, 1, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*) offsetof(VertexData, custom)); eglGetError(); } string testApp::readFile(string fileName) { stringstream ss; ifstream frag_file; frag_file.open(ofToDataPath(fileName.c_str(),true).c_str()); if(!frag_file.is_open()) { printf("Cannot open vertex shader.\n"); ::exit(1); } string line; while(getline(frag_file, line)) { ss << line << "\n"; } return ss.str(); } //-------------------------------------------------------------- void testApp::update(){ } //-------------------------------------------------------------- void testApp::draw(){ // reset gl. glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, ofGetWidth()/ofGetHeight(), 0.1, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0,0,-10); // and draw our vbo glBindBuffer(GL_ARRAY_BUFFER, buffer); eglGetError(); glDrawArrays(GL_QUADS, 0, 4); eglGetError(); } //-------------------------------------------------------------- void testApp::keyPressed(int key){ if(key == ' ') { float s = 4; float t = (ofGetElapsedTimef()); float v = (1.0+sin(t)*0.5); VertexData points[4]; points[0].pos.set(-s, s, 0); points[1].pos.set(s,s, 0); points[2].pos.set(s,-s,0); points[3].pos.set(-s, -s, 0); points[0].col.set(v,0,0); points[1].col.set(0,v,0); points[2].col.set(0,0,v); points[3].col.set(v,0,v); points[0].custom = v; points[1].custom = 1.0 * v; points[2].custom = 1.0 * v; points[3].custom = 0.8 * v; glBindBuffer(GL_ARRAY_BUFFER, buffer); eglGetError(); glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData)* 4, &points[0].pos.x, GL_DYNAMIC_DRAW); eglGetError(); } }