Expand/Shrink

OpenGL/WebGL

WebGL is not based on OpenGL. It is based on OpenGL ES 2.0. The same OpenGL ES found on Android and iOS.

There are significant differences between OpenGL and OpenGL ES.
While OpenGL ES is a subset of OpenGL it is missing the old deprecated fixed function pipeline that so many people continue to use and so many outdated tutorials still teach (like Nehe GL).

What is the fixed function pipeline? Anything having to do with glVertex, glColor, glNormal, glLight, glPushMatrix, glPopMatrix, glMatrixMode, etc... in GLSL using any of the variables that access the fixed function data like gl_Vertex, gl_Normal, gl_Color, gl_MultiTexCoord, gl_FogCoord, gl_ModelViewMatrix and the various other matrices from the fixed function pipeline.

Those are all removed from OpenGL ES 2.0 and therefore do not exist in WebGL

OpenGL is a cross-language, cross-platform application programming interface (API) for rendering 2D and 3D vector graphics.
pGUI includes a simple OpenGL/WebGL wrapper. Credit is especially due to Mic, on whose work much of this wrapper is based, particularly the euglr9.zip contribution of Mar 23/08, and also to Jean-Marc DURO, for making things cross-platform (not that I actually use glfw, just some opengl bits of that wrapper). Further, I have unifed(/am in the process of unifying) OpenGL and WebGL into a single compatible API.

Of course drawing a 3D scene is no mean feat, you can get a glimpse of just how complicated it is by visiting this little webgl state diagram. If that does not confuse and frighten you, there is something wrong with you. OpenGL/WebGL is quite probably the simplest possible interface to getting the job done, but it inevitably involves more than just a few steps, though hopefully none of the individual steps should be completely overwhelming.
Essentially it is just a matter of poking a bucketload of data and then telling it to go and do its thing, with the slight compilcation that vertext and fragment shaders are written in a completely different language (as constant strings).
Unfortunately I am not the person to ask, and am not going to make any attempt whatsoever to document that other language.

This only attempts to document routines and constants actually used in the provided demos. It is not a tutorial, just a quick lookup. It is also far from complete. To be honest, I understood a little bit of 3D math when writing some of the rosettacode examples, but I cannot really say the same about the opengl examples I have translated. My apologies if any of the code samples provided are somewhat out-of-date, but at least they work (flw).

I should also note that it is not my main intention to create a library suitable for full-screen flat-out gaming; something from PCAN (and not necessarily p2js compatible) may be more appropriate for that task. Instead it is to embed useful graphics capability in a desktop or web app such as a CAD program, or perhaps a utility to create/design gaming levels rather than the game itself. I will happily accept reduced performance in return for cross-platform operation, or a simpler and cleaner API. Several of the demos have been modified to minimise CPU usage, which of course would be important on a shared, remote, or battery-powered platform.

Pete’s super quick intro to OpenGL/WebGL

First and foremost you need to define all the points/vertices and faces of the model.
For a 2D 'F' draw three rectangles, one upright and two rungs. We will treat that as 3 faces.
There are four distinct x (left/right) values and five distinct y (up/down) values, and 12 vertices,
two of which are the same point (where the upright and the top rung meet).
For a 3D 'F' replicate that with a different z (front/back), now we have 24 vertices.
The right hand side of the upright needs (splitting into) two faces and the left hand side of both rungs have none, plus
the top of the upright and the top of the top rung are merged into a single face.
In total we have 16 faces1, each of which we are going to specify as two triangles2.
1 Just to clarify and not of any great significance, 6 of those faces are flat and 5 each are horizonal/vertical edge-on.
2 While OpenGL 1.0’s glBegin() supported quads and polygons, OpenGL ES 2.0 and WebGL stop at triangles.


Let that all sink in. If you cannot imagine or arrange a few suitable things on the desktop in front of you to resemble a 3D 'F', and verify the numbers above (esp 16), then I’m afraid to say you are a lost cause. Don’t worry about the units: internally OpenGL maps everything to 0.0..1.0 or -1.0..+1.0 as needed anyway, along with the "camera" position, so just use the numbers you find easiest. Do however bear in mind that we are (probably) going to be rotating about {0,0,0}, so making that the "centre of gravity" usually helps, though of course you can specify things more naturally and then add/subtract some {dx,dy,dz} to/from every point. See sequence F_positions in demo\pGUI\HelloF.exw (these notes are replicated in that source file).

It is important to note that each face can be drawn using two triangles in 144 different ways, which could have a significant impact when it comes to applying textures. There are two diagonals that split a rectangle into two triangles, but you can start on any one of those four, and draw by starting on any of the three corners of a triangle and go clockwise or anticlockwise, so 4*3*2*3*2=144. On top of that we have different pixel coordinates for Canvas Draw and OpenGL, as well as low-level differences between OpenGL (on the desktop) and WebGL (as in a browser). We need to take the simplest route possible here, and one suggested way to do that is to use the glSimpleA7texcoords() routine.

Next we want to apply a texture to each of those faces. This is a simple matter of matching each and every vertex previously specified to the corresponding position on the texture. We can make things much simpler by declaring the faces in a consistent manner and applying textures using a standard platform-specific approach, which means opengl.e vs opengl.js in this context. Applying a world map to a sphere needs a bit more math and many more triangles, but it is basically the same.

The rest is fairly standard: store it with glBufferData(), and specify what it all means first by calling glVertexAttribPointer() with the right size, type, and possibly stride settings, and finally glDrawArrays() with the desired mode, here GL_TRIANGLES, not forgetting the total length. Of course there are all sorts of other things to achieve smoothing, rotation, lighting effects, and so on, but the quick intro endeth here.

Further reading

Obviously I assume you know how to use google or whatever your favourite search engine might be. Be warned however the vast majority of "OpenGL" stuff is still 1.0, you are probably better off looking for "WebGL" instead, or maybe "OpenGL ES 2.0". Five out of six links from the previous version of this page have been commented out for that reason. I am not planning on killing off, for instance, demo\pGUI\vol_fog.exw, but I am not planning on ever supporting that API version under pwa/p2js either.

If I get time, I might translate some of the examples from https://en.wikibooks.org/wiki/OpenGL_Programming and maybe add those tutorials here.

Of course someone is going to say "why don't you use three.js" (or similar)... well, it is not desktop compatible and even minified it clocks in at a "lightweight" 1.7MB, so that’s a firm no thanks from me. That being said, I am always open to handy shortcuts that simplify things.

What about Vulkan? Get back to me when you can run it in a browser (ie don’t ever get back to me). Again, if a decent enough desktop-only but otherwise cross-platform wrapper crops up I’ll be more than happy to host a copy on PCAN and include a link to that from the docs, but I am not likely to be too keen on spending too much time promoting or documenting it, unless it comes with some really cool demos!

While opengl.e defines GL_TRUE and GL_FALSE as simple aliases for the standard true and false constants, I would recommend using the builtins instead (to avoid any suggestion or fear they are somehow different) and in fact even better replace say expr=GL_TRUE and expr=GL_FALSE with just expr and not expr respectively, likewise GLboolean with bool.