OpenGL core profile is centred around OpenGL 3.2 and allows you to use OpenGL without the old deprecated stuff and as such is likely before long to be a common minimum standard for support.
There are some slight differences with GLSL if you’re maybe been concentrating on mobile shaders, but nothing thats too far beyond the pale.
Lets have a quick wander down the code and see whats what…
#include "gl_core_3_2.h" #include <GLFW/glfw3.h>
The first thing to mention is I’ve used a code generator to make me a procedure loader to load up all the functions that appeared after OpenGL1.1 – why this isn’t done automatically when a core profile context is created, well maybe I shouldn’t expect “common” sense !
I used the generator here which both seems robust and should work OK on other platforms too (Although I could guess developing windows OpenGL applications is not a joyous experience!)
Next we have a very simple set of shaders to make up a simple shader program
const char* vertex_shader = /*01*/ "#version 150 core \n" /*02*/ " \n" /*03*/ "in vec3 vp; \n" /*04*/ "uniform float u_time; \n" /*05*/ "out float blank; \n" /*06*/ " \n" /*07*/ "void main () { \n" /*08*/ " vec4 p = vec4(vp, 1.0); \n" /*09*/ " p.x = p.x + (sin(u_time+p.y)/4.0); \n" /*10*/ " p.y = p.y + (cos(u_time+p.x)/4.0); \n" /*11*/ " gl_Position = p; \n" /*12*/ " blank = sin((u_time+p.x+p.y)*4.0); \n" /*13*/ "}";
const char* fragment_shader = /*01*/ "#version 150 core \n" /*02*/ " \n" /*03*/ "out vec4 frag_colour; \n" /*04*/ "uniform float u_time; \n" /*05*/ "in float blank; \n" /*06*/ " \n" /*07*/ "void main () { \n" /*08*/ " frag_colour = vec4 (0.5, abs(sin(u_time)), abs(cos(u_time)), 1.0); \n" /*09*/ " if (blank<0) frag_colour = vec4 (0.5, abs(cos(u_time)), abs(sin(u_time)), 1.0); \n" /*10*/ "}
There’s not a great deal to say here, except do note that I label line numbers, although you might have to do a little maintenance – doing this is very helpful when shader compiling fails…
if (!glfwInit ()) { fprintf (stderr, "10 ERROR: could not start GLFW3\n"); return 1; } // tell glfw we want the core profile glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow (640, 480, "Hello Triangle", NULL, NULL); if (!window) { fprintf (stderr, "20 ERROR: could not open window with GLFW3\n"); glfwTerminate(); return 1; }
I like to let GLFW do the heavy lifting and as you can see making a compatible context is no where near as painful as EGL can be!
glfwMakeContextCurrent (window); if(ogl_LoadFunctions() == ogl_LOAD_FAILED) { fprintf (stderr, "30 ERROR: failed to load gl functions\n"); glfwTerminate(); return 1; }
Once we actually have a context created we can go ahead and load up all those missing function pointers.
The rest of the code such that it is – is very simple “ordinary” GL code, coming from GLES2.0 (mobile) arena, the shader is where a far bit has been changed and that you need a vertex array.