OpenGL has four different major versions, not counting the versions for mobile devices and embedded systems (OpenGL|ES) and the Web via JavaScript (WebGL). Just like Direct3D 11 has a different way of doing things than Direct3D 8, so does OpenGL 3 have a different way of doing things than OpenGL 1. The big difference is that OpenGL versions are mostly just add-ons to the older versions (but not entirely).
On top of the different editions and versions of OpenGL, the main OpenGL also added the concept of profiles. Namely the Compatibility Profile (which enables support for APIs from older versions) and the Core Profile (which disables those old APIs). Things like glBegin
simply don't work when you use the Core Profile but will when you use the Compatibility Profile (which is the default).
As one further major complication, some implementations of OpenGL (like Apple's, among others) will only enable newer OpenGL features when you're using the Core Profile. This means that you must stop using older APIs in order to use newer APIs.
You then end up with several very confusing scenarios for tutorials:
- The tutorial is old and only uses deprecated APIs.
- The tutorial is new and well-written and only uses Core-compatible APIs.
- The tutorial is new but makes the mistake of assuming that you're working with a driver that enables all APIs in Compatibility mode, and freely mixes both new and old APIs.
- The tutorial is for a different edition of OpenGL like OpenGL|ES that doesn't support any of the old APIs at all, in any version.
Things like glBegin
are part of what's sometimes called the immediate mode API. This is also super confusing because there's no such thing as a retained mode in OpenGL and "immediate mode" already had a different definition in graphics. It's much better to just refer to those as OpenGL 1.x APIs as they've been obsolete since OpenGL 2.1.
OpenGL's 1.x API would immediately submit vertices to the graphics pipeline back in the old days. This worked well when the speed of the hardware that rendered vertices was roughly on par with the speed of the CPU generating the vertex data. OpenGL back then just offloaded the triangle rasterization and not much else.
These days, the GPU can chew through massive numbers of vertices at very high speeds while performing advanced vertex and pixel transformation and the CPU simply cannot even remotely keep up. On top of that, the interface between the CPU and the GPU has been designed around this speed difference meaning that it's not even possible to submit vertices to the GPU one at a time anymore.
All GL drivers must emulate glBegin
by internally allocating a vertex buffer, putting the vertices submitted with glVertex
into this buffer, and then submitting that whole buffer in a single draw call when glEnd
is called. The overhead of these functions is far greater than if you just updated the vertex buffer yourself, which is why some documentation will (very mistakenly!) refer to vertex buffers as "an optimization" (it's not an optimization; it's the only way to actually talk to the GPU).
There are various other APIs that have been deprecated or obsoleted in OpenGL over the years. The so-called fixed-function pipeline is another such piece. Some documentation might still use this pipeline or mix with the programmable pipeline. The fixed-function pipeline comes from the olden days when graphics cards hard-coded all of the math used to render 3D scenes and the OpenGL API was limited to setting some configuration values for that math. These days the hardware has very little hard-coded math and (just like your CPU) runs user-supplied programs (often called shaders) instead.
Once again the drivers must emulate the old API as the fixed-function features simply aren't present on hardware anymore. This means that the driver has a bunch of compatibility shaders embedded in it that execute the old math from the fixed-function days which is used when you don't supply your own shaders. The old OpenGL functions that modify that old fixed-function state (like the old OpenGL lighting API) are actually using modern OpenGL features like uniform buffers to feed these values to the driver's compatibility shaders.
Drivers that support compatibility have to do a lot of behind-the-scenes work just to figure out when you're using these obsolete features and making sure that you can combine them with modern features smoothly, which adds overhead and greatly complicates the driver. This is one of the reasons that some drivers force you to enable the Core Profile to get at newer features; it simplifies their driver internals greatly by not having to support both the old and new APIs being used simultaneously.
A lot of documentation may recommend that you start with the old APIs simply on account of them being easier to get started with. Direct3D solved this problem for beginners by offering a companion library (DirectX Tool Kit) that provides simpler drawing APIs and pre-written shaders which can be freely mixed with raw Direct3D 11 usage as your expertise grows. The wider OpenGL community has mostly stuck with the Compatibility Profile for beginners, unfortunately, which is problematic as again there are systems that do not let you mix old OpenGL APIs with the newer ones. There are unofficial libraries and tools for simpler rendering on the new OpenGL with varying levels of features and target use cases and languages (MonoGame for .NET users for instance), but nothing officially endorsed or widely agreed upon.
Documentation you're finding may not even be for OpenGL but may be for one of the other similar APIs. OpenGL|ES 1.x had fixed-function rendering but did not have the OpenGL 1.x APIs for vertex submission. OpenGL|ES 2.x+ and WebGL 1+ do not have any fixed-function features at all and there is no backwards compatibility modes for those APIs.
These APIs look very very similar to main OpenGL; they're not quite compatible, but there are official extensions to OpenGL that some (not all) drivers support to become compatible with OpenGL|ES (which WebGL is based on). Because things weren't confusing enough before.
glBegin
andglEnd
have been deprecated because they're extremely inefficient for the current graphics architectures \$\endgroup\$