Portal:OpenGL Concepts

From OpenGL Wiki
Jump to navigation Jump to search
V · E
What is OpenGL?
Opengl Tiny.gif
OpenGL is the name for the specification that describes the behavior of a rasterization-based rendering system. It defines the API through which a client application can control this system. The OpenGL rendering system is carefully specified to make hardware implementations allowable.

Hardware vendors, the people who make GPUs, are responsible for writing implementations of the OpenGL rendering system. Their implementations, commonly called "drivers", translate OpenGL API commands into GPU commands. If a particular piece of hardware is unable to implement all of the OpenGL specification via hardware, the hardware vendor must still provide this functionality, typically via a software-based implementation of the features missing from hardware.

OpenGL is generally not something you directly install. It is not a library or separate downloadable package. You simply install drivers for your graphics hardware, and the OpenGL implementation is part of the installation.

OpenGL is typically exposed to software as an API written against C. However, there are bindings for many other languages, built on top of that API. For users of C or C++, there will be a need, on most platforms, to explicitly load functions of interest. There are many libraries that handle this process mostly automatically.

OpenGL functions have a well-defined naming convention (which is usually consistently followed). They also use a specific set of well-defined types, to aid in cross-platform portability.

The OpenGL specification is governed by the OpenGL ARB, which is a member of the Khronos Group. They develop new versions of the specification and decide how to expose various hardware features through OpenGL. Major hardware vendors, such as NVIDIA, AMD, and Intel, are members of the ARB.

OpenGL has had a number of different versions. The most recent version of OpenGL is 4.6. Recently (since 2008), the ARB has regularly released a new version of OpenGL yearly, with each update adding significant new features.
V · E
OpenGL Context

The OpenGL specification defines the concept of the Context. The context contains all of the information that will be used by the OpenGL system to render, when the system is given a rendering command. A context effectively is OpenGL, because OpenGL cannot be used without one.

OpenGL contexts are local to a particular application; you cannot peek at another application's contexts. However, each application can have multiple contexts. Each context is completely separate and isolated from one another, with one exception. Objects (see below) can be shared between contexts, if the contexts are setup to do so when they are initially created.

All OpenGL functions operate on the context which is "current". This is very much like a global variable that every OpenGL function operates on. OpenGL functions do not work unless a context is current.

Note: To be technical, OpenGL function pointers retrieved from one context should not be used with function pointers retrieved from another context. That being said, this will almost never cause problems, so long as the same driver is servicing both contexts.
While the OpenGL specification details the behavior of contexts, it does not cover the creation of them. This is governed by platform-specific APIs. Therefore, while OpenGL code is generally platform-neutral, it is always dependent on some platform-specific code to create and destroy OpenGL contexts.

The OpenGL specification, usually, defines the behavior of commands such that they will execute in the order given, and that every subsequent command must behave as if all prior commands have completed and their contents are visible. However, it is important to keep in mind that this is how OpenGL is specified, not how it is implemented.

OpenGL implementations attempt to do as much work asynchronously as possible. When a rendering function returns, odds are good that the actual rendering operation has not even started yet, let alone has finished. However, as long as you don't query any state that would be changed by that rendering command (such as the content of the destination images), you would not be able to tell the difference.

The key phrase to remember from the above definition is "as if". The implementation must make rendering look synchronous, while being as asynchronous as possible. So for best performance, you must avoid querying state that has been affected by rendering commands. You must also avoid changing the contents of objects that will be used by rendering commands that have been sent but may not yet have executed.

The OpenGL Memory Model governs when state set by one OpenGL command becomes visible to other commands. Normally, the memory model is perfectly sequential and synchronous: state set by one command is immediately visible to any subsequent command, but not any prior ones. However, there are certain cases where the model breaks down or otherwise requires explicit synchronization.

Rendering to the same image as one is sampling from is one such case. A second case is when dealing with multiple contexts that have objects shared between them. State set from one context may not be immediately visible in another; special considerations need to be taken.

The big one has to do with arbitrary image reads/writes in GL 4.2+. The use of this feature (as well as some related ones) completely throws out any implicit GL memory model, thus forcing all synchronization for these operations on the user.
V · E
Errors and Debugging

Debugging an OpenGL application can be difficult. But OpenGL does provide ways to make debugging more reasonable.

OpenGL requires its functions to check their parameters for mistakes or inconsistencies, and emit errors should these occur. If an error occurs, in the vast majority of cases, the function emitting the error will have no effect.

Because error checking is a very manual process, many OpenGL implementations provide access to Debug Output. This functionality is a powerful mechanism for handling testing these kinds of errors without being explicit about it. There are also a number of Debugging Tools available to help track down OpenGL errors and other issues.

The OpenGL error mechanism does not test all possible incorrect uses of the API; this is mainly for performance reasons. Most untested mistakes result in improper rendering and must be manually found, though debugging tools can help in these cases too.
V · E

The OpenGL context contains information used by the rendering system. This information is called State, which has given rise to the saying that OpenGL is a "state machine". A piece of state is simply some value stored in the OpenGL context.

Every individual piece of state in the OpenGL context can be uniquely identified. The OpenGL specification document has a massive table at the end, defining what these identifiers are and which state they can be used to query. Not all of the identifiers are as simple as an enumeration, as OpenGL state can be in arrays, where each entry must be queried individually.

When a context is created, every piece of state is initialized to a well-defined default value. The state table defines what the initial value is for every piece of OpenGL state. Note that this does not mean that a freshly created context can be used to render with without some setup work.

OpenGL functions can be grouped into 3 broad categories: functions that set state into the context, functions that query state, and functions that render given the current state of the context. Functions that query state use the unique identifier to name which state value they retrieve. The state table in the specification says which functions are used to query each state value.

Certain OpenGL state values are aggregated into objects. This allows groups of state to be stored and reset with a single command. Most objects in OpenGL are defined as groups of context state, even if that context state is not available if no object is currently in use.

Most objects in OpenGL follow the same general paradigm and naming convention. Object names are GLuints; these are handles used to identify an object. Live objects are created with a function of the form glGen*; those objects are deleted with a call to the equivalent glDelete*. Objects are aggregates of state, and state exists within the OpenGL context. Therefore, to modify an object or to use it to render something, the object must first be bound to the context. The function to do this is of the form glBind*. Any functions that modify or query the state that this object contains will modify/query the object's internal state.

The object 0 is special, and it has different behaviors for different object types. For many objects, 0 represents "not an object", much like a NULL pointer. For a few object types, it is a default object, which can not be destroyed. In general, with the exception of Framebuffers, you should treat 0 like NULL: an invalid object.

The Rendering Pipeline is the sequence of steps that are taken by the OpenGL rendering system when the user issues a Drawing Command. The pipeline is a sequential series of steps, where each step performs some computation and passes its data to the next step for further processing.

The OpenGL specification is very clear on the order in which objects are rendered. Specifically, objects are rendered in the exact order the user provides. While implementations are free to adjust the order internally, the rendered output must be as if it were processed in order.

Certain stages of the rendering pipeline are programmable. The term for a programmable stage of the pipeline is Shader, and the programs that are executed by that pipeline stage are called "Shaders".

In OpenGL, shaders are written in the OpenGL Shading Language. Many OpenGL implementations offer extensions that provide alternative languages.

A Framebuffer is a OpenGL object that aggregates images together, which rendering operations can use as their eventual destination. OpenGL contexts usually have a Default Framebuffer, which is usually associated with a window or other display device. Rendering operations that are intended to be directly visualized should go to the default framebuffer.

Users can construct Framebuffer Objects, framebuffers built from images provided by Textures or Renderbuffers. These are useful for rendering data off-screen; the data can later be transferred to the default framebuffer.

In OpenGL version 3.0, a lot of redundant yet long-standing functionality was marked Deprecated. This means that it was still supported, but the ARB would be willing to remove it in later versions. In OpenGL 3.1, most of this functionality was removed (and therefore is not deprecated). In OpenGL 3.2, the removed functionality was spun off into a "compatibility profile" specification. The core profile would continue to not have this functionality.

This wiki focuses primarily on the core profile of OpenGL.