OpenGL core profile – an introduction

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.

 

Enjoy!

 

Leave a Reply

Your email address will not be published. Required fields are marked *