`GL`
Prev | Chapter 3. User's Guide | Next

## `GL`

## OpenGL Library; API versions 1.0 and 1.1

### Selection and Feedback buffers

Normally in OpenGL to use a selection buffer one would do the following:

    GLuint buffer[SIZE];
    glSelectBuffer(SIZE, buffer);
    glRenderMode(GL_SELECT);
    /* draw some stuff */
    GLint count = glRenderMode(GL_RENDER);
    /* parse the selection buffer */

In Python this accomplished like this:

    glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
    glRenderMode(GL_SELECT)
    # draw some stuff
    buffer = glRenderMode(GL_RENDER)
    for hit_record in buffer:
        min_depth, max_depth, names = hit_record
        # do something with the record

Feedback buffers are used in the same way except that each item in the buffer is tuple `(token, value)`, where value is either a passthrough token or a list of vertices. Note that if `glRenderMode` returns a buffer than it also resets OpenGL's pointer for the corresponding buffer. This means that the buffer returned by `glRenderMode` is independent of future calls to `glRenderMode`, i.e. it will not be overwritten by any such future calls. This makes the returned buffer somewhat thread-safe. It also means that every call to `glRenderMode(GL_SELECT | GL_FEEDBACK)` needs to preceded by a call to `glSelectBuffer` or `glFeedbackBuffer` first, i.e. the following code will not work

    glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
    glRenderMode(GL_SELECT)
    # draw some stuff
    buffer = glRenderMode(GL_RENDER)
    # do another selection
    glRenderMode(GL_SELECT)
    # draw some stuff
    buffer = glRenderMode(GL_RENDER)

Instead one must

    glSelectBuffer(SIZE) # allocate a selection buffer of SIZE elements
    glRenderMode(GL_SELECT)
    # draw some stuff
    buffer = glRenderMode(GL_RENDER)
    # do another selection
    glSelectBuffer(SIZE) allocate a new selection buffer
    glRenderMode(GL_SELECT)
    # draw some stuff
    buffer = glRenderMode(GL_RENDER)

In previous versions of PyOpenGL in order to perform selection one would use the `glSelectWithCallback` function. This function is still available, but the only thing that it does in addition to the method described above is setup the projection matrix using `gluPickMatrix`.

### Array Routines

Each call which sets an array pointer, such as `glVertexPointer`, will have many variants. First there will a function which is identical that of the specification. For the `pointer` argument one should pass a string. Also note that the stride values are used.

Next there will a set of functions named

    glXPointer{ub|b|us|s|ui|i|f|d}

These will usually take as a single argument a multidimensional array of values. The type argument is controlled by the suffix of the function (`ub` is unsigned byte, etc.) All other arguments are derived from the dimensions of the array.

So for `glColorPointer` we have:

    glColorPointer(size, type, stride, pointer) -> None
    glColorPointerub(pointer[][]) -> None
    glColorPointerb(pointer[][]) -> None
    glColorPointerus(pointer[][]) -> None
    glColorPointers(pointer[][]) -> None
    glColorPointerui(pointer[][]) -> None
    glColorPointeri(pointer[][]) -> None
    glColorPointerf(pointer[][]) -> None
    glColorPointerd(pointer[][]) -> None

This same decoration strategy is used for other array functions besides `glXPointer`. For instance, `glDrawElements` has the Python binding:

    glDrawElements(mode, count, type, indices) -> None

where `indices` is expected to be a string. There are also the decorated bindings

    glDrawElementsub(mode, indices[]) -> None
    glDrawElementsus(mode, indices[]) -> None
    glDrawElementsui(mode, indices[]) -> None

where "indices" is now a single dimensional array.

When calling a `glColorPointer`, `glVertexPointer`, etc. Python needs to allocate memory to store the values that OpenGL needs. This memory is reference counted and takes into account function calls like `glPushClientAttrib` and `glPopClientAttrib`. To force this memory to be released one just need to make a call `glColorPointerub(None)`.

Currently `glPushClientAttrib` will always set the `GL_CLIENT_VERTEX_ARRAY_BIT` flag as `glPopClientAttrib` has no way of knowing that flag was set and the state of the flag is needed to know whether or not to decrement the pointer locks on the allocated memory. This may change in the future. That said, surrounding array use `glPushClientAttrib`/`glPopClientAttrib` is a good way to force the release of any allocated memory, but make sure that all calls to `glXPointer`, etc. are within the `ClientAttrib` block if you chose to use this scheme.

### Note

Since all the memory allocation is automatic there is no need for `glGetPointerv` function, so it is excluded.

### Note

The function `glInterleavedArrays` is also present, but it does not have the variants that the others do (i.e., no `glInterleavedArraysf`)

### Warning

If you write an extension module which makes calls to the pointer functions and expects to interact with PyOpenGL safely it should push the client state (from within the extension) before and after array use.

### Image Routines

`glDrawPixels` and the other image/texturing functions have much the same decoration scheme as the array functions. For `glDrawPixels` there is the standard function which expects a string as the pixel data:

    glDrawPixels(width, height, format, type, pixels) -> None

This function will respect the parameters set by `glPixelStore{i|f}`. There is also a collection of variants which take a multidimensional array as the data source and set `glPixelStore{i|f}` automatically. For example:

    glDrawPixelsub(format, pixels) -> None

Notice that `width` and `height` are inferred from the pixel data and the type is GLubyte.

### Error Handling

In OpenGL the current error status is retrieved with the function `glGetError`. This function returns an error code and clears the current error status at the same time. On some distributed systems multiple errors may be generated at a time. In that case it is necessary to call `glGetError` multiple times.

PyOpenGL does not expose the `glGetError`. Instead it automatically checks the error status and throws an instance of `GL.GLerror` on an error. This is a more "Pythonic" approach. `GL.GLerror` is a subclass of `EnvironmentError` and has a `errno` and `msg` like `EnvironmentError`. In the case of multiple errors the `errno` attribute will be set to a tuple of error numbers and `msg` will be a concatenation of the error messages for each error.

Prev | Home | Next
Chapter 3. User's Guide | Up | `GLU`