Table Of Contents

Previous topic

psychopy.tools.filetools

Next topic

psychopy.tools.imagetools

This Page

Quick links

psychopy.tools.gltools

OpenGL related helper functions.

createFBO([attachments]) Create a Framebuffer Object.
attach(attachPoint, imageBuffer) Attach an image to a specified attachment point on the presently bound FBO.
isComplete() Check if the currently bound framebuffer is complete.
deleteFBO(fbo) Delete a framebuffer.
blitFBO(srcRect[, dstRect, filter]) Copy a block of pixels between framebuffers via blitting.
useFBO(*args, **kwds) Context manager for Framebuffer Object bindings.
createRenderbuffer(width, height[, …]) Create a new Renderbuffer Object with a specified internal format.
deleteRenderbuffer(renderBuffer) Free the resources associated with a renderbuffer.
createTexImage2D(width, height[, target, …]) Create a 2D texture in video memory.
createTexImage2DMultisample(width, height[, …]) Create a 2D multisampled texture.
deleteTexture(texture) Free the resources associated with a texture.
createVBO(data[, size, dtype, target]) Create a single-storage array buffer, often referred to as Vertex Buffer Object (VBO).
createVAO(vertexBuffers[, indexBuffer]) Create a Vertex Array Object (VAO) with specified Vertex Buffer Objects.
drawVAO(vao[, mode, flush]) Draw a vertex array using glDrawArrays.
deleteVBO(vbo) Delete a Vertex Buffer Object (VBO).
deleteVAO(vao) Delete a Vertex Array Object (VAO).
createMaterial([params, textures, face]) Create a new material.
useMaterial(material[, useTextures]) Use a material for proceeding vertex draws.
createLight([params]) Create a point light source.
useLights(lights[, setupOnly]) Use specified lights in successive rendering operations.
setAmbientLight(color) Set the global ambient lighting for the scene when lighting is enabled.
loadObjFile(objFile) Load a Wavefront OBJ file (*.obj).
loadMtlFile(mtlFilePath[, texParameters]) Load a material library (*.mtl).
getIntegerv(parName) Get a single integer parameter value, return it as a Python integer.
getFloatv(parName) Get a single float parameter value, return it as a Python float.
getString(parName) Get a single string parameter value, return it as a Python UTF-8 string.
getOpenGLInfo() Get general information about the OpenGL implementation on this machine.

Function details

psychopy.tools.gltools.createFBO(attachments=())

Create a Framebuffer Object.

Parameters:attachments (list or tuple of tuple) – Optional attachments to initialize the Framebuffer with. Attachments are specified as a list of tuples. Each tuple must contain an attachment point (e.g. GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, etc.) and a buffer descriptor type (Renderbuffer or TexImage2D). If using a combined depth/stencil format such as GL_DEPTH24_STENCIL8, GL_DEPTH_ATTACHMENT and GL_STENCIL_ATTACHMENT must be passed the same buffer. Alternatively, one can use GL_DEPTH_STENCIL_ATTACHMENT instead. If using multisample buffers, all attachment images must use the same number of samples!. As an example, one may specify attachments as ‘attachments=(( GL.GL_COLOR_ATTACHMENT0, frameTexture), (GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRenderBuffer))’.
Returns:Framebuffer descriptor.
Return type:Framebuffer

Notes

  • All buffers must have the same number of samples.
  • The ‘userData’ field of the returned descriptor is a dictionary that can be used to store arbitrary data associated with the FBO.
  • Framebuffers need a single attachment to be complete.

Examples

# empty framebuffer with no attachments fbo = createFBO() # invalid until attachments are added

# create a render target with multiple color texture attachments colorTex = createTexImage2D(1024,1024) # empty texture depthRb = createRenderbuffer(800,600,internalFormat=GL.GL_DEPTH24_STENCIL8)

# attach images GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo.id) attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_ATTACHMENT, depthRb) attach(GL.GL_STENCIL_ATTACHMENT, depthRb) # or attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)

# above is the same as with useFBO(fbo):

attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_ATTACHMENT, depthRb) attach(GL.GL_STENCIL_ATTACHMENT, depthRb)

# examples of userData some custom function might access fbo.userData[‘flags’] = [‘left_eye’, ‘clear_before_use’]

# depth only texture (for shadow mapping?) depthTex = createTexImage2D(800, 600,

internalFormat=GL.GL_DEPTH_COMPONENT24, pixelFormat=GL.GL_DEPTH_COMPONENT)

fbo = createFBO([(GL.GL_DEPTH_ATTACHMENT, depthTex)]) # is valid

# discard FBO descriptor, just give me the ID frameBuffer = createFBO().id

psychopy.tools.gltools.attach(attachPoint, imageBuffer)

Attach an image to a specified attachment point on the presently bound FBO.

:param attachPoint int: Attachment point for ‘imageBuffer’ (e.g. GL.GL_COLOR_ATTACHMENT0). :param imageBuffer: Framebuffer-attachable buffer descriptor. :type imageBuffer: TexImage2D or Renderbuffer

Returns:
Return type:None

Examples

# with descriptors colorTex and depthRb GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo) attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb) GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, lastBoundFbo)

# same as above, but using a context manager with useFBO(fbo):

attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb)
psychopy.tools.gltools.isComplete()

Check if the currently bound framebuffer is complete.

Returns:
Return type:obj:`bool’
psychopy.tools.gltools.deleteFBO(fbo)

Delete a framebuffer.

Returns:
Return type:obj:`None’
psychopy.tools.gltools.blitFBO(srcRect, dstRect=None, filter=9729)

Copy a block of pixels between framebuffers via blitting. Read and draw framebuffers must be bound prior to calling this function. Beware, the scissor box and viewport are changed when this is called to dstRect.

Parameters:
  • srcRect (list of int) – List specifying the top-left and bottom-right coordinates of the region to copy from (<X0>, <Y0>, <X1>, <Y1>).
  • dstRect (list of int or None) – List specifying the top-left and bottom-right coordinates of the region to copy to (<X0>, <Y0>, <X1>, <Y1>). If None, srcRect is used for dstRect.
  • filter (int) – Interpolation method to use if the image is stretched, default is GL_LINEAR, but can also be GL_NEAREST.
Returns:

Return type:

None

Examples

# bind framebuffer to read pixels from GL.glBindFramebuffer(GL.GL_READ_FRAMEBUFFER, srcFbo)

# bind framebuffer to draw pixels to GL.glBindFramebuffer(GL.GL_DRAW_FRAMEBUFFER, dstFbo)

gltools.blitFBO((0,0,800,600), (0,0,800,600))

# unbind both read and draw buffers GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)

psychopy.tools.gltools.useFBO(*args, **kwds)

Context manager for Framebuffer Object bindings. This function yields the framebuffer name as an integer.

:param fbo int or Framebuffer: OpenGL Framebuffer Object name/ID or descriptor.

Yields:int – OpenGL name of the framebuffer bound in the context.
Returns:
Return type:None

Examples

# FBO bound somewhere deep in our code GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, someOtherFBO)

# create a new FBO, but we have no idea what the currently bound FBO is fbo = createFBO()

# use a context to bind attachments with bindFBO(fbo):

attach(GL.GL_COLOR_ATTACHMENT0, colorTex) attach(GL.GL_DEPTH_ATTACHMENT, depthRb) attach(GL.GL_STENCIL_ATTACHMENT, depthRb) isComplete = gltools.isComplete()

# someOtherFBO is still bound!

psychopy.tools.gltools.createRenderbuffer(width, height, internalFormat=32856, samples=1)

Create a new Renderbuffer Object with a specified internal format. A multisample storage buffer is created if samples > 1.

Renderbuffers contain image data and are optimized for use as render targets. See https://www.khronos.org/opengl/wiki/Renderbuffer_Object for more information.

Parameters:
  • width (int) – Buffer width in pixels.
  • height (int) – Buffer height in pixels.
  • internalFormat (int) – Format for renderbuffer data (e.g. GL_RGBA8, GL_DEPTH24_STENCIL8).
  • samples (int) – Number of samples for multi-sampling, should be >1 and power-of-two. Work with one sample, but will raise a warning.
Returns:

A descriptor of the created renderbuffer.

Return type:

Renderbuffer

Notes

The ‘userData’ field of the returned descriptor is a dictionary that can be used to store arbitrary data associated with the buffer.

psychopy.tools.gltools.deleteRenderbuffer(renderBuffer)

Free the resources associated with a renderbuffer. This invalidates the renderbuffer’s ID.

Returns:
Return type:obj:`None’
psychopy.tools.gltools.createTexImage2D(width, height, target=3553, level=0, internalFormat=32856, pixelFormat=6408, dataType=5126, data=None, unpackAlignment=4, texParameters=())

Create a 2D texture in video memory. This can only create a single 2D texture with targets GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE.

Parameters:
  • width (int) – Texture width in pixels.
  • height (int) – Texture height in pixels.
  • target (int) – The target texture should only be either GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE.
  • level (int) – LOD number of the texture, should be 0 if GL_TEXTURE_RECTANGLE is the target.
  • internalFormat (int) – Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
  • pixelFormat (int) – Pixel data format (e.g. GL_RGBA, GL_DEPTH_STENCIL)
  • dataType (int) – Data type for pixel data (e.g. GL_FLOAT, GL_UNSIGNED_BYTE).
  • data (ctypes or None) – Ctypes pointer to image data. If None is specified, the texture will be created but pixel data will be uninitialized.
  • unpackAlignment (int) – Alignment requirements of each row in memory. Default is 4.
  • texParameters (list of tuple of int) – Optional texture parameters specified as a list of tuples. These values are passed to ‘glTexParameteri’. Each tuple must contain a parameter name and value. For example, texParameters=[(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR), (GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)]
Returns:

A TexImage2D descriptor.

Return type:

TexImage2D

Notes

The ‘userData’ field of the returned descriptor is a dictionary that can be used to store arbitrary data associated with the texture.

Previous textures are unbound after calling ‘createTexImage2D’.

Examples

import pyglet.gl as GL # using Pyglet for now

# empty texture textureDesc = createTexImage2D(1024, 1024, internalFormat=GL.GL_RGBA8)

# load texture data from an image file using Pillow and NumPy from PIL import Image import numpy as np im = Image.open(imageFile) # 8bpp! im = im.transpose(Image.FLIP_TOP_BOTTOM) # OpenGL origin is at bottom im = im.convert(“RGBA”) pixelData = np.array(im).ctypes # convert to ctypes!

width = pixelData.shape[1] height = pixelData.shape[0] textureDesc = gltools.createTexImage2D(

width, height, internalFormat=GL.GL_RGBA, pixelFormat=GL.GL_RGBA, dataType=GL.GL_UNSIGNED_BYTE, data=texture_array.ctypes, unpackAlignment=1, texParameters=[(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR),

(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)])

GL.glBindTexture(GL.GL_TEXTURE_2D, textureDesc.id)

psychopy.tools.gltools.createTexImage2DMultisample(width, height, target=37120, samples=1, internalFormat=32856, texParameters=())

Create a 2D multisampled texture.

Parameters:
  • width (int) – Texture width in pixels.
  • height (int) – Texture height in pixels.
  • target (int) – The target texture (e.g. GL_TEXTURE_2D_MULTISAMPLE).
  • samples (int) – Number of samples for multi-sampling, should be >1 and power-of-two. Work with one sample, but will raise a warning.
  • internalFormat (int) – Internal format for texture data (e.g. GL_RGBA8, GL_R11F_G11F_B10F).
  • texParameters (list of tuple of int) – Optional texture parameters specified as a list of tuples. These values are passed to ‘glTexParameteri’. Each tuple must contain a parameter name and value. For example, texParameters=[(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR), (GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)]
Returns:

A TexImage2DMultisample descriptor.

Return type:

TexImage2DMultisample

psychopy.tools.gltools.deleteTexture(texture)

Free the resources associated with a texture. This invalidates the texture’s ID.

Returns:
Return type:obj:`None’
psychopy.tools.gltools.createVBO(data, size=3, dtype=5126, target=34962)

Create a single-storage array buffer, often referred to as Vertex Buffer Object (VBO).

Parameters:
  • data (list or tuple of float or int) – Coordinates as a 1D array of floats (e.g. [X0, Y0, Z0, X1, Y1, Z1, …])
  • size (int) – Number of coordinates per-vertex, default is 3.
  • dtype (int) – Data type OpenGL will interpret that data as, should be compatible with the type of ‘data’.
  • target (int) – Target used when binding the buffer (e.g. GL_VERTEX_ARRAY)
Returns:

A descriptor with vertex buffer information.

Return type:

VertexBufferObject

Notes

Creating vertex buffers is a computationally expensive operation. Be sure to load all resources before entering your experiment’s main loop.

Examples

# vertices of a triangle verts = [ 1.0, 1.0, 0.0, # v0

0.0, -1.0, 0.0, # v1

-1.0, 1.0, 0.0] # v2

# load vertices to graphics device, return a descriptor vboDesc = createVBO(verts, 3)

# draw GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vboDesc.id) GL.glVertexPointer(vboDesc.vertexSize, vboDesc.dtype, 0, None) GL.glEnableClientState(vboDesc.bufferType) GL.glDrawArrays(GL.GL_TRIANGLES, 0, vboDesc.indices) GL.glFlush()

psychopy.tools.gltools.createVAO(vertexBuffers, indexBuffer=None)

Create a Vertex Array Object (VAO) with specified Vertex Buffer Objects. VAOs store buffer binding states, reducing CPU overhead when drawing objects with vertex data stored in VBOs.

Parameters:
  • vertexBuffers (list of tuple) – Specify vertex attributes VBO descriptors apply to.
  • indexBuffer (list of int, optional) – Index array of elements. If provided, an element array is created from the array. The returned descriptor will have isIndexed=True. This requires the VAO be drawn with glDrawElements instead of glDrawArrays.
Returns:

A descriptor with vertex array information.

Return type:

VertexArrayObject

Examples

# create a VAO vaoDesc = createVAO(vboVerts, vboTexCoords, vboNormals)

# draw the VAO, renders the mesh drawVAO(vaoDesc, GL.GL_TRIANGLES)

psychopy.tools.gltools.drawVAO(vao, mode=4, flush=False)

Draw a vertex array using glDrawArrays. This method does not require shaders.

Parameters:
  • vao (VertexArrayObject) – Vertex Array Object (VAO) to draw.
  • mode (int, optional) – Drawing mode to use (e.g. GL_TRIANGLES, GL_QUADS, GL_POINTS, etc.)
  • flush (bool, optional) – Flush queued drawing commands before returning.
Returns:

Return type:

None

Examples

# create a VAO vaoDesc = createVAO(vboVerts, vboTexCoords, vboNormals)

# draw the VAO, renders the mesh drawVAO(vaoDesc, GL.GL_TRIANGLES)

psychopy.tools.gltools.deleteVBO(vbo)

Delete a Vertex Buffer Object (VBO).

Returns:
Return type:obj:`None’
psychopy.tools.gltools.deleteVAO(vao)

Delete a Vertex Array Object (VAO). This does not delete array buffers bound to the VAO.

Returns:
Return type:obj:`None’
psychopy.tools.gltools.createMaterial(params=(), textures=(), face=1032)

Create a new material.

Parameters:params (list of tuple, optional) – List of material modes and values. Each mode is assigned a value as (mode, color). Modes can be GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_SHININESS or GL_AMBIENT_AND_DIFFUSE. Colors must be a tuple of 4 floats which specify reflectance values for each RGBA component. The value of GL_SHININESS should be a single float. If no values are specified, an empty material will be created.
:param textures list of tuple, optional: List of texture units and TexImage2D descriptors. These will be written
to the ‘textures’ field of the returned descriptor. For example, [(GL.GL_TEXTURE0, texDesc0), (GL.GL_TEXTURE1, texDesc1)]. The number of texture units per-material is GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
Parameters:face (int, optional) – Faces to apply material to. Values can be GL_FRONT_AND_BACK, GL_FRONT and GL_BACK. The default is GL_FRONT_AND_BACK.
Returns:A descriptor with material properties.
Return type:Material

Examples

# The values for the material below can be found at # http://devernay.free.fr/cours/opengl/materials.html

# create a gold material gold = createMaterial([

(GL.GL_AMBIENT, (0.24725, 0.19950, 0.07450, 1.0)), (GL.GL_DIFFUSE, (0.75164, 0.60648, 0.22648, 1.0)), (GL.GL_SPECULAR, (0.628281, 0.555802, 0.366065, 1.0)), (GL.GL_SHININESS, 0.4 * 128.0)])

# use the material when drawing useMaterial(gold) drawVAO( … ) # all meshes will be gold useMaterial(None) # turn off material when done

# create a red plastic material, but define reflectance and shine later red_plastic = createMaterial()

# you need to convert values to ctypes! red_plastic.values[GL_AMBIENT] = (GLfloat * 4)(0.0, 0.0, 0.0, 1.0) red_plastic.values[GL_DIFFUSE] = (GLfloat * 4)(0.5, 0.0, 0.0, 1.0) red_plastic.values[GL_SPECULAR] = (GLfloat * 4)(0.7, 0.6, 0.6, 1.0) red_plastic.values[GL_SHININESS] = 0.25 * 128.0

# set and draw useMaterial(red_plastic) drawVertexbuffers( … ) # all meshes will be red plastic useMaterial(None)

psychopy.tools.gltools.useMaterial(material, useTextures=True)

Use a material for proceeding vertex draws.

Parameters:
  • material (Material or None) – Material descriptor to use. Default material properties are set if None is specified. This is equivalent to disabling materials.
  • useTextures (bool) – Enable textures. Textures specified in a material descriptor’s ‘texture’ attribute will be bound and their respective texture units will be enabled. Note, when disabling materials, the value of useTextures must match the previous call. If there are no textures attached to the material, useTexture will be silently ignored.
Returns:

Return type:

None

Notes

  1. If a material mode has a value of None, a color with all components 0.0 will be assigned.
  2. Material colors and shininess values are accessible from shader programs after calling ‘useMaterial’. Values can be accessed via built-in ‘gl_FrontMaterial’ and ‘gl_BackMaterial’ structures (e.g. gl_FrontMaterial.diffuse).

Examples

# use the material when drawing useMaterial(metalMaterials.gold) drawVAO( … ) # all meshes drawn will be gold useMaterial(None) # turn off material when done

psychopy.tools.gltools.createLight(params=())

Create a point light source.

psychopy.tools.gltools.useLights(lights, setupOnly=False)

Use specified lights in successive rendering operations. All lights will be transformed using the present modelview matrix.

Parameters:
  • lights (List of Light or None) – Descriptor of a light source. If None, lighting is disabled.
  • setupOnly (bool, optional) – Do not enable lighting or lights. Specify True if lighting is being computed via fragment shaders.
Returns:

Return type:

None

psychopy.tools.gltools.setAmbientLight(color)

Set the global ambient lighting for the scene when lighting is enabled. This is equivalent to GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, color) and does not contribute to the GL_MAX_LIGHTS limit.

Parameters:color (tuple) – Ambient lighting RGBA intensity for the whole scene.
Returns:
Return type:None

Notes

If unset, the default value is (0.2, 0.2, 0.2, 1.0) when GL_LIGHTING is enabled.

psychopy.tools.gltools.loadObjFile(objFile)

Load a Wavefront OBJ file (*.obj).

Parameters:objFile (str) – Path to the *.OBJ file to load.
Returns:
Return type:WavefrontObjModel

Notes

  1. This importer should work fine for most sanely generated files. Export your model with Blender for best results, even if you used some other package to create it.
  2. The model must be triangulated, quad faces are not supported.

Examples

# load a model from file objModel = loadObjFile(‘/path/to/file.obj’)

# load the material (*.mtl) file, textures are also loaded materials = loadMtl(‘/path/to/’ + objModel.mtlFile)

# apply settings GL.glEnable(GL.GL_CULL_FACE) GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthFunc(GL.GL_LEQUAL) GL.glDepthMask(GL.GL_TRUE) GL.glShadeModel(GL.GL_SMOOTH) GL.glCullFace(GL.GL_BACK) GL.glDisable(GL.GL_BLEND)

# lights useLights(light0)

# draw the model for group, vao in obj.drawGroups.items():

useMaterial(materials[group]) drawVAO(vao)

# disable materials and lights useMaterial(None) useLights(None)

psychopy.tools.gltools.loadMtlFile(mtlFilePath, texParameters=None)

Load a material library (*.mtl).

psychopy.tools.gltools.getIntegerv(parName)

Get a single integer parameter value, return it as a Python integer.

Parameters:pName (:obj:`int’) – OpenGL property enum to query (e.g. GL_MAJOR_VERSION).
Returns:
Return type:int
psychopy.tools.gltools.getFloatv(parName)

Get a single float parameter value, return it as a Python float.

Parameters:pName (:obj:`float’) – OpenGL property enum to query.
Returns:
Return type:int
psychopy.tools.gltools.getString(parName)

Get a single string parameter value, return it as a Python UTF-8 string.

Parameters:pName (:obj:`int’) – OpenGL property enum to query (e.g. GL_VENDOR).
Returns:
Return type:str
psychopy.tools.gltools.getOpenGLInfo()

Get general information about the OpenGL implementation on this machine. This should provide a consistent means of doing so regardless of the OpenGL interface we are using.

Returns are dictionary with the following fields:

vendor, renderer, version, majorVersion, minorVersion, doubleBuffer, maxTextureSize, stereo, maxSamples, extensions

Supported extensions are returned as a list in the ‘extensions’ field. You can check if a platform supports an extension by checking the membership of the extension name in that list.

Returns:
Return type:OpenGLInfo

Examples

Working with Framebuffer Objects (FBOs):

Creating an empty framebuffer with no attachments:

fbo = createFBO()  # invalid until attachments are added

Create a render target with multiple color texture attachments:

colorTex = createTexImage2D(1024,1024)  # empty texture
depthRb = createRenderbuffer(800,600,internalFormat=GL.GL_DEPTH24_STENCIL8)

GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo.id)
attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
attach(GL.GL_DEPTH_ATTACHMENT, depthRb)
attach(GL.GL_STENCIL_ATTACHMENT, depthRb)
# or attach(GL.GL_DEPTH_STENCIL_ATTACHMENT, depthRb)
GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0)

Attach FBO images using a context. This automatically returns to the previous FBO binding state when complete. This is useful if you don’t know the current binding state:

with useFBO(fbo):
    attach(GL.GL_COLOR_ATTACHMENT0, colorTex)
    attach(GL.GL_DEPTH_ATTACHMENT, depthRb)
    attach(GL.GL_STENCIL_ATTACHMENT, depthRb)

How to set userData some custom function might access:

fbo.userData['flags'] = ['left_eye', 'clear_before_use']

Binding an FBO for drawing/reading:

GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb.id)

Depth-only framebuffers are valid, sometimes need for generating shadows:

depthTex = createTexImage2D(800, 600,
                            internalFormat=GL.GL_DEPTH_COMPONENT24,
                            pixelFormat=GL.GL_DEPTH_COMPONENT)
fbo = createFBO([(GL.GL_DEPTH_ATTACHMENT, depthTex)])

Deleting a framebuffer when done with it. This invalidates the framebuffer’s ID and makes it available for use:

deleteFBO(fbo)