Portal:OpenGL Objects

From OpenGL Wiki
Jump to: navigation, search

OpenGL defines the concept of an object as being an OpenGL construct that contains some amount of state (ie: values). OpenGL defines a fair number of object types, with many uses throughout the OpenGL API. Some object types are container objects; these objects primarily store references to other objects. Container objects cannot be shared across OpenGL Contexts.

Most OpenGL objects follow a certain set of conventions as to their APIs and use. Objects are not implemented in a C or C++ style, as pointers to some data. They are GLuint integer handles, called "names", that reference the actual data stored in the object. Functions that generate objects will be named glGen*, where * is the object name. Names can be deleted, using a function of the form glDelete*.

Generating a name does not (usually) create the object itself. To do that, it must first be bound to the context. Binding an object to the context means that the object's contained state now becomes part of the context's state. Functions that modify or query those pieces of state will set or retrieve values stored in the object. And rendering functions that rely on these pieces of state will get their data from the object.

Objects are bound with functions of the form glBind*, where * is the object type. Most OpenGL objects can be bound to multiple locations in the context. These locations, or targets, represent different places where the object's state can be used in different ways. So how rendering works can change based on which target an object is bound to.

A buffer object is a linear array of memory, who's storage is managed by the OpenGL context. There are many OpenGL APIs that use buffer objects as source or destination data for reading/writing operations. There are many functions for allocating buffer object storage, updating its contents, and for efficiently loading data continuously.

Buffer objects have a wide variety of uses, with each target roughly corresponding to a specific usage of a buffer object. An important thing to remember is that, subject to the limits of the OpenGL Memory Model, you may freely interchange buffer objects. A buffer object can be used as the source of vertex data in one instance, then used as the destination for vertex writing in another, then used as the source for pixel data transfers, etc.

A Framebuffer Object (FBO) is a container object that stores a series of images that can, as a collection, be used as a Framebuffer. Images can be added to or removed from an FBO as needed. Images can come from Texture objects or Renderbuffer Objects. In this way, textures can be render targets.

The set of images added to an FBO must satisfy certain constraints before the FBO can be utilized. These constraints are fairly minimal, such has having valid storage and using valid image formats.

Rendering to an image in a texture while reading from the same image is not generally allowed by the OpenGL memory model, though there are ways to make it work. Violating such constraints yields undefined behavior.
A Vertex Array Object is a container object that stores the state that describes arrays of vertex data that will be used in rendering commands. It stores all of the Buffer Objects and other vertex format state needed to understand arrays of vertices and index data.

A Query Object represents certain kinds of state, where accessing the state directly would cause severe synchronization problems or degraded performance. So a query object thus represents a result that is not necessarily available yet. Most of these queries are based on rendering operations that happen within a specific, defined boundary.

There are a number of types of queries. There are queries for how many samples in a particular rendering operation passed all of the various post-fragment processing tests and the Fragment Shader itself. That is, how much of a rendered object is visible (if any). There are queries for how long the GPU took to execute some set of commands. And there are queries for how many primitives were written by a Transform Feedback operation.

Like textures, the type of query object is assigned the first time the query object is used. Unlike textures and other OpenGL objects, query objects are never "bound". Because query operations are scoped, query objects use a special begin/end pair of functions. These functions define the type of the query object. Using an existing query object with the wrong type is an error.

A Texture is an object that contains one or more images, of a certain dimensionality. These images can be sampled from shaders or access via direct image load/store. The images they store can also be attached to Framebuffer Objects. Storage for texture images can be allocated and updated in numerous ways.

Texture objects are peculiar in a certain sense. When you first bind a texture object to a target, the texture object is permanently associated with that target; it is an error to bind it to another target. This is because the target defines what kind of texture the object represents. The texture's type determines how many images it may have, how many dimensions those images have, etc.

Texture objects store a number of intrinsic parameters that define certain aspects of the texture. They can also store a number of sampling parameters, which define how the texture is accessed via samplers. These parameters can be overridden with Sampler Objects.

A Sampler Object is an object that describes how texture objects are accessed from a Shader. These parameters include how accesses to the texture are to be filtered, whether comparison mode is active, texture coordinate wrapping, and so forth. Texture objects also have these parameters, but a sampler object bound to the same texture image unit will override them.

Unlike most OpenGL objects, you can modify the state of a sampler object without binding it.
A Renderbuffer Object is an object that represents a single image of a specific Image Format. Such objects can only be used as render targets for Framebuffer Objects; they cannot be read from, outside of any operation that reads from the Framebuffer that the renderbuffer happens to be attached to. They are only useful if you need a particular image for rendering to, such as wanting to render colors to a texture, but needing a depth buffer for Depth Tests. The depth buffer could be a renderbuffer rather than a texture.
A Program Pipeline Object is a container object that stores a series of separable program objects that contain shaders. Though program objects do not follow the standard OpenGL object model, program pipeline objects do. Program pipelines are light-weight objects that simply represent a specific sequence of shader stages to execute in a rendering operation.
A Transform Feedback Object is a container object that represents the state needed for a transform feedback operation. It stores the set of Buffer Objects that are being written to. Feedback objects also store how many primitives were written in a particular feedback operation; this stored value is implicitly used in certain rendering commands. Feedback objects can also preserve the current write position, so that feedback operations can be paused and resumed.

Some objects in OpenGL do not fit into the general object paradigm described above. These irregular objects are not considered "OpenGL Objects" in the definitive sense stated above. But they are objects (self-contained pieces of state), they are part of the OpenGL API, and they do have state which can be set and queried.

The irregular objects are described below:

V · E
Shader/Program Objects

A Program Object stores the executable code and uniform state for one or more Shader stages. The most common means of building them involves the creation of Shader Objects, which represent strings of text in the OpenGL Shading Language. Shader objects are compiled, and if successful, one or more shader objects is linked into a program.

In both cases, the user can query whether compilation or linking failed, and the error messages produced by any such failures.
A Sync Object is used to detect which commands have finished executing and which have not. Fence sync objects can be inserted into the command stream, and the user can query when they've completed. Since all OpenGL commands complete in order, if a fence object has completed, so have all operations issued before the fence.