OpenGL

OpenGL is a confusing mess...

OpenGL ES2

Here is the dirty OpenGL secret: WebGL and Android are based on OpenGL ES 2.0. The "current" (2023) OpenGL version according to Khronos is 4.6. The style of programming for OpenGL ES 2.0 is very different than OpenGL 4.6.

OpenGL eras

I think you can roughly separate OpenGL into three "eras":

1) The "fixed function pipeline" era 2) The "getting rid of the fixed function pipeline" era 3) The modern era

The term "fixed function pipeline" basically means no shaders. Starting with OpenGL 3.1 the fixed function pipeline was removed, meaning you had to write a shader to use OpenGL. The "getting rid of the fixed function pipeline" era I define because it was still available, and even without it the API still had quite a "fixed" feel to it.

OpenGL 2.0 was the first version to have shaders available in the core. OpenGL ES 2.0 is based off OpenGL 2.1 but with the fixed function pipeline stripped out (along with some other things).

GLSL versions are all over the place

You have a) OpenGL version number, b) GLSL version number, c) GLSL declaration in source code (#version xxx). Here is a handy table from Wikipedia:

GLSL version    OpenGL version      Shader header
-------------------------------------------------
1.10            2.0                 #version 110
1.20            2.1                 #version 120
1.30            3.0                 #version 130
1.40            3.1                 #version 140
1.50            3.2                 #version 150
3.30            3.3                 #version 330
4.00            4.0                 #version 400
4.10            4.1                 #version 410
4.20            4.2                 #version 420
4.30            4.3                 #version 430
4.40            4.4                 #version 440
4.50            4.5                 #version 450
4.60            4.6                 #version 460

Starting at OpenGL 3.3 the GLSL version number starts to make sense. But that is for non-ES. Here is the same for OpenGL ES:

GLSL version    OpenGL ES   Web GL version  Based on        Shader header
-------------------------------------------------------------------------
1.00            2.0         1.0             1.20            #version 100
3.00            3.0         2.0             3.30            #version 300 es
3.10            3.1                         GLSLES 3.00     #version 310 es
3.20            3.2                         GLSLES 3.10     #version 320 es 

So, imagine you want to target the maximum number of platforms with a single OpenGL codebase, with minimal changes:

  • OpenGL ES 2.0 will give you the widest coverage.
  • On desktop this is OpenGL 2.1 with GLSL version 1.20 - #version 120.
  • On Android this is OpenGL ES 2.0 with GLSL version 1.00 - #version 100.
  • On WebGL this is WebGL 1.0 with GLSL GLSL version 1.00 - #version 100.

However, realise that OpenGL ES 2.0 was released in 2009! In 2023 that is 14 years old! And it's very difficult (if not impossible) to write the exact same code that will run on all platforms. If you can take the compatibility hit you can choose:

  • OpenGL ES 3.0.
  • On desktop this is OpenGL 3.3 with GLSL version 3.3 - #version 330.
  • On Android this is OpenGLE ES 3.0 with GLSL version 3.0 - #version 300 es.
  • On WebGL this is WebGL 2.0 with GLSL version 3.0 - #version 300 es.

So note that if you choose something above OpenGL ES 3.0 you can forget about compatibility. From the Android developer site:

Caution: Regardless of the Android platform version, a device cannot
support the OpenGL ES 3.0 API unless the device manufacturer provides an
implementation of this graphics pipeline.

OpenGL is a specification not an implementation

What does this mean? It means that some part (or all) of the rendering pipeline could be implemented in software, where hardware (or drivers) don't support that functionality. On Linux the main OpenGL implementation is "Mesa", but NVIDIA also make a proprietary OpenGL implementation. Mesa allows you to run OpenGL applications (slowly) on computers without a GPU because it will just emulate everything in software (CPU).

OpenGL loaders

If your using OpenGL ES 2.0 or OpenGL ES 3.0, on desktop Linux there are specific header files:

#include <GLES2/gl2.h>
#include <GLES3/gl3.h>

However, if you want to use OpenGL 3.3 on Linux there is no "gl33.h" include. If you try to use "GL/gl.h" there will be a ton of undefined functions when you try to compile! Why is this? OpenGL is a specification, and the underlying "engine" (eg: Mesa) can implement several "profiles" simultainiously. An OpenGL profile is a subset of all possible OpenGL functions. So when you want to use OpenGL 3.3 core profile you must connect all possible functions with the underlying Mesa implementation functions for that profile. This is such a huge pain that there are several projects that do this for you:

  • GLEW - include "glew.h" and call "glewInit()".
  • GL3W - A python script that generates a header file, then call "gl3wInit()".
  • Galogen - Also generates a header file for your desired profile.
  • glad - Does some magic, not sure.
  • And many more...

You can read all about it here. The huge pain here is that while you might compile your program on one machine with a specific OpenGL implementation, your program might run on another machine with a different OpenGL implementation. So you end up with code like this:

if (GLAD_GL_EXT_framebuffer_multisample) {
    /* GL_EXT_framebuffer_multisample is supported */ 
}
if (GLAD_GL_VERSION_3_0) {
    /* We support at least OpenGL version 3 */
}

Oh, and forget about Apple

Because they have dropped OpenGL support entirely.

Fully cross-platform accelerated 3d graphics?

Nope. Pick a game engine.