psychopy.tools.gltools

OpenGL related helper functions.

createProgram() Create an empty program object for shaders.
compileShader(shaderSrc, shaderType) Compile shader GLSL code and return a shader object.
deleteObject(obj) Delete a shader or program object.
attachShader(program, shader) Attach a shader to a program.
detachShader(program, shader) Detach a shader object from a program.
linkProgram(program) Link a shader program.
validateProgram(program) Check if the program can execute given the current OpenGL state.
useProgram(program) Use a program object’s executable shader attachments in the current OpenGL rendering state.
createProgramObjectARB() Create an empty program object for shaders.
compileShaderObjectARB(shaderSrc, shaderType) Compile shader GLSL code and return a shader object.
embedShaderSourceDefs(shaderSrc, defs) Embed preprocessor definitions into GLSL source code.
deleteObjectARB(obj) Delete a program or shader object.
attachObjectARB(program, shader) Attach a shader object to a program.
detachObjectARB(program, shader) Detach a shader object from a program.
linkProgramObjectARB(program) Link a shader program object.
validateProgramARB(program) Check if the program can execute given the current OpenGL state.
useProgramObjectARB(program) Use a program object’s executable shader attachments in the current OpenGL rendering state.
getInfoLog(obj) Get the information log from a shader or program.
getUniformLocations(program[, builtins]) Get uniform names and locations from a given shader program object.
getAttribLocations(program[, builtins]) Get attribute names and locations from the specified program object.
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(fbo) 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.createProgram()[source]

Create an empty program object for shaders.

Returns:OpenGL program object handle retrieved from a glCreateProgram call.
Return type:int

Examples

Building a program with vertex and fragment shader attachments:

myProgram = createProgram()  # new shader object

# compile vertex and fragment shader sources
vertexShader = compileShader(vertShaderSource, GL.GL_VERTEX_SHADER)
fragmentShader = compileShader(fragShaderSource, GL.GL_FRAGMENT_SHADER)

# attach shaders to program
attachShader(myProgram, vertexShader)
attachShader(myProgram, fragmentShader)

# link the shader, makes `myProgram` attachments executable by their
# respective processors and available for use
linkProgram(myProgram)

# optional, validate the program
validateProgram(myProgram)

# optional, detach and discard shader objects
detachShader(myProgram, vertexShader)
detachShader(myProgram, fragmentShader)

deleteObject(vertexShader)
deleteObject(fragmentShader)

You can install the program for use in the current rendering state by calling:

useProgram(myShader) # OR glUseProgram(myShader)
# set uniforms/attributes and start drawing here ...
psychopy.tools.gltools.compileShader(shaderSrc, shaderType)[source]

Compile shader GLSL code and return a shader object. Shader objects can then be attached to programs and made executable on their respective processors.

Parameters:
  • shaderSrc (str, list of str) – GLSL shader source code.
  • shaderType (GLenum) – Shader program type (eg. GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, etc.)
Returns:

OpenGL shader object handle retrieved from a glCreateShader call.

Return type:

int

Examples

Compiling GLSL source code and attaching it to a program object:

# GLSL vertex shader source
vertexSource =             '''
    #version 330 core
    layout (location = 0) in vec3 vertexPos;

    void main()
    {
        gl_Position = vec4(vertexPos, 1.0);
    }
    '''
# compile it, specifying `GL_VERTEX_SHADER`
vertexShader = compileShader(vertexSource, GL.GL_VERTEX_SHADER)
attachShader(myProgram, vertexShader)  # attach it to `myProgram`
psychopy.tools.gltools.deleteObject(obj)[source]

Delete a shader or program object.

Parameters:obj (int) – Shader or program object handle. Must have originated from a createProgram(), compileShader(), glCreateProgram or glCreateShader call.
psychopy.tools.gltools.attachShader(program, shader)[source]

Attach a shader to a program.

Parameters:
  • program (int) – Program handle to attach shader to. Must have originated from a createProgram() or glCreateProgram call.
  • shader (int) – Handle of shader object to attach. Must have originated from a compileShader() or glCreateShader call.
psychopy.tools.gltools.detachShader(program, shader)[source]

Detach a shader object from a program.

Parameters:
  • program (int) – Program handle to detach shader from. Must have originated from a createProgram() or glCreateProgram call.
  • shader (int) – Handle of shader object to detach. Must have been previously attached to program.
psychopy.tools.gltools.linkProgram(program)[source]

Link a shader program. Any attached shader objects will be made executable to run on associated GPU processor units when the program is used.

Parameters:

program (int) – Program handle to link. Must have originated from a createProgram() or glCreateProgram call.

Raises:
  • ValueError – Specified program handle is invalid.
  • RuntimeError – Program failed to link. Log will be dumped to sterr.
psychopy.tools.gltools.validateProgram(program)[source]

Check if the program can execute given the current OpenGL state.

Parameters:program (int) – Handle of program to validate. Must have originated from a createProgram() or glCreateProgram call.
psychopy.tools.gltools.useProgram(program)[source]

Use a program object’s executable shader attachments in the current OpenGL rendering state.

In order to install the program object in the current rendering state, a program must have been successfully linked by calling linkProgram() or glLinkProgram.

Parameters:program (int) – Handle of program to use. Must have originated from a createProgram() or glCreateProgram call and was successfully linked. Passing 0 or None disables shader programs.

Examples

Install a program for use in the current rendering state:

useProgram(myShader)

Disable the current shader program by specifying 0:

useProgram(0)
psychopy.tools.gltools.createProgramObjectARB()[source]

Create an empty program object for shaders.

This creates an Architecture Review Board (ARB) program variant which is compatible with older GLSL versions and OpenGL coding practices (eg. fixed function) on some platforms. Use *ARB variants of shader helper functions (eg. compileShaderObjectARB instead of compileShader) when working with these ARB program objects. This was included for legacy support of existing PsychoPy shaders. However, it is recommended that you use createShader() and follow more recent OpenGL design patterns for new code (if possible of course).

Returns:OpenGL program object handle retrieved from a glCreateProgramObjectARB call.
Return type:int

Examples

Building a program with vertex and fragment shader attachments:

myProgram = createProgramObjectARB()  # new shader object

# compile vertex and fragment shader sources
vertexShader = compileShaderObjectARB(
    vertShaderSource, GL.GL_VERTEX_SHADER_ARB)
fragmentShader = compileShaderObjectARB(
    fragShaderSource, GL.GL_FRAGMENT_SHADER_ARB)

# attach shaders to program
attachObjectARB(myProgram, vertexShader)
attachObjectARB(myProgram, fragmentShader)

# link the shader, makes `myProgram` attachments executable by their
# respective processors and available for use
linkProgramObjectARB(myProgram)

# optional, validate the program
validateProgramARB(myProgram)

# optional, detach and discard shader objects
detachObjectARB(myProgram, vertexShader)
detachObjectARB(myProgram, fragmentShader)

deleteObjectARB(vertexShader)
deleteObjectARB(fragmentShader)

Use the program in the current OpenGL state:

useProgramObjectARB(myProgram)
psychopy.tools.gltools.compileShaderObjectARB(shaderSrc, shaderType)[source]

Compile shader GLSL code and return a shader object. Shader objects can then be attached to programs and made executable on their respective processors.

Parameters:
  • shaderSrc (str, list of str) – GLSL shader source code text.
  • shaderType (GLenum) – Shader program type. Must be *_ARB enums such as GL_VERTEX_SHADER_ARB, GL_FRAGMENT_SHADER_ARB, GL_GEOMETRY_SHADER_ARB, etc.
Returns:

OpenGL shader object handle retrieved from a glCreateShaderObjectARB call.

Return type:

int

psychopy.tools.gltools.deleteObjectARB(obj)[source]

Delete a program or shader object.

Parameters:obj (int) – Program handle to attach shader to. Must have originated from a createProgramObjectARB(), compileShaderObjectARB, `glCreateProgramObjectARB() or glCreateShaderObjectARB call.
psychopy.tools.gltools.attachObjectARB(program, shader)[source]

Attach a shader object to a program.

Parameters:
  • program (int) – Program handle to attach shader to. Must have originated from a createProgramObjectARB() or glCreateProgramObjectARB call.
  • shader (int) – Handle of shader object to attach. Must have originated from a compileShaderObjectARB() or glCreateShaderObjectARB call.
psychopy.tools.gltools.detachObjectARB(program, shader)[source]

Detach a shader object from a program.

Parameters:
  • program (int) – Program handle to detach shader from. Must have originated from a createProgramObjectARB() or glCreateProgramObjectARB call.
  • shader (int) – Handle of shader object to detach. Must have been previously attached to program.
psychopy.tools.gltools.linkProgramObjectARB(program)[source]

Link a shader program object. Any attached shader objects will be made executable to run on associated GPU processor units when the program is used.

Parameters:

program (int) – Program handle to link. Must have originated from a createProgramObjectARB() or glCreateProgramObjectARB call.

Raises:
  • ValueError – Specified program handle is invalid.
  • RuntimeError – Program failed to link. Log will be dumped to sterr.
psychopy.tools.gltools.validateProgramARB(program)[source]

Check if the program can execute given the current OpenGL state. If validation fails, information from the driver is dumped giving the reason.

Parameters:program (int) – Handle of program object to validate. Must have originated from a createProgramObjectARB() or glCreateProgramObjectARB call.
psychopy.tools.gltools.useProgramObjectARB(program)[source]

Use a program object’s executable shader attachments in the current OpenGL rendering state.

In order to install the program object in the current rendering state, a program must have been successfully linked by calling linkProgramObjectARB() or glLinkProgramObjectARB.

Parameters:program (int) – Handle of program object to use. Must have originated from a createProgramObjectARB() or glCreateProgramObjectARB call and was successfully linked. Passing 0 or None disables shader programs.

Examples

Install a program for use in the current rendering state:

useProgramObjectARB(myShader)

Disable the current shader program by specifying 0:

useProgramObjectARB(0)

Notes

Some drivers may support using glUseProgram for objects created by calling createProgramObjectARB() or glCreateProgramObjectARB.

psychopy.tools.gltools.getInfoLog(obj)[source]

Get the information log from a shader or program.

This retrieves a text log from the driver pertaining to the shader or program. For instance, a log can report shader compiler output or validation results. The verbosity and formatting of the logs are platform-dependent, where one driver may provide more information than another.

This function works with both standard and ARB program object variants.

Parameters:obj (int) – Program or shader to retrieve a log from. If a shader, the handle must have originated from a compileShader(), glCreateShader, createProgramObjectARB() or glCreateProgramObjectARB call. If a program, the handle must have came from a createProgram(), createProgramObjectARB(), glCreateProgram or glCreateProgramObjectARB call.
Returns:Information log data. Logs can be empty strings if the driver has no information available.
Return type:str
psychopy.tools.gltools.getUniformLocations(program, builtins=False)[source]

Get uniform names and locations from a given shader program object.

This function works with both standard and ARB program object variants.

Parameters:
  • program (int) – Handle of program to retrieve uniforms. Must have originated from a createProgram(), createProgramObjectARB(), glCreateProgram or glCreateProgramObjectARB call.
  • builtins (bool, optional) – Include built-in GLSL uniforms (eg. gl_ModelViewProjectionMatrix). Default is False.
Returns:

Uniform names and locations.

Return type:

dict

Examples

Get the location uniform modelMatrix in myShader and set it matrix using a Numpy array:

modelMatrix = numpy.identity(4)  # example

# if using Pygelt's GL functions, you need to convert to a pointer
modelMatrix = modelMatrix.ctypes.data_as(ctypes.POINTER(GL.GLfloat))

uniforms = getUniformLocations(myShader)
useProgram(myShader)

glUniformMatrix4fv(
    uniforms['modelMatrix'],
    1,
    GL_TRUE,  # transpose, since Numpy matrices are row-major in memory
    modelMatrix)

You can check if a shader has a uniform before setting it. This allows for the same sub-routine to flexibly handle different shader types, as long as the uniform variables have the same names and types:

# get the uniform names and locations. In the shader, we have defined
# `uniform vec4 specularColor`.
uniforms = getUniformLocations(myShader)
hasSpecularColor = 'specularColor' in uniforms.keys()

if hasSpecularColor:
    glUniform4f(uniforms['specularColor'],
        1.0, 1.0, 1.0, 1.0)

# Another example to handle cases where a shader may be compiled with or
# without texture code paths.
#
# If the shader has `uniform sampler2D diffuseTexture` defined, we
# enable textures and bind it to the appropriate texture unit.
if 'diffuseTexture' in uniforms.keys():
    # enable textures if the shader calls for it
    glEnable(GL_TEXTURE_2D)
    glActiveTexture(GL_TEXTURE0)
    glColor4f(1.0, 1.0, 1.0, 1.0)
    glColorMask(True, True, True, True)
    glBindTexture(GL_TEXTURE_2D, texId)

    # diffuse at texture unit `0`
    glUniform4i(uniforms['diffuseTexture'], 0)
    # remember to disable textures when done!
else:
    # no diffuse texture, just have the material track the current color
    glColor4f(1.0, 1.0, 1.0, 1.0)
psychopy.tools.gltools.getAttribLocations(program, builtins=False)[source]

Get attribute names and locations from the specified program object.

This allows you to set vertex attribute pointers by name instead of by index, allowing indices to vary between shaders. Furthermore, it allows for checking if a shader has a particular attribute.

This function works with both standard and ARB program object variants.

Parameters:
  • program (int) – Handle of program to retrieve attributes. Must have originated from a createProgram(), createProgramObjectARB(), glCreateProgram or glCreateProgramObjectARB call.
  • builtins (bool, optional) – Include built-in GLSL attributes (eg. gl_Vertex). Default is False.
Returns:

Attribute names and locations.

Return type:

dict

Examples

Get the attribute locations in the shader and use them to specify vertex attribute pointers within a vertex array (VAO) context:

# Get vertex attribute locations in our shader (`myShader`). Within the
# shader we have attributes defined as:
#
#   layout(location = 0) in vec3 pos;
#   layout(location = 1) in vec2 textureCoords;
#   layout(location = 2) in vec3 normals;
#
# Calling `getAttribLocations` will return a dictionary like this:
#
#   {'pos': 0, 'textureCoords': 1, 'normals': 2}
#
attribLocations = getAttribLocations(myShader)

# create a VAO
vaoId = GLuint()
glGenVertexArrays(1, byref(vaoId))
glBindVertexArray(vaoId)

# bind the buffer storing vertex attribute, here they are interleaved
glBindBuffer(GL.GL_ARRAY_BUFFER, vboId)

# use the attribute index for `pos` to bind the vertex position buffer
attrib = attribLocations['pos']
glVertexAttribPointer(attrib, 3, GL_FLOAT, GL_FALSE, posStride, 0)
glEnableVertexAttribArray(attrib)

attrib = attribLocations['textureCoords']
glVertexAttribPointer(
    attrib, 2, GL_FLOAT, GL_FALSE, texCoordStride, texCoordOffset)
glEnableVertexAttribArray(attrib)

attrib = attribLocations['normals']
glVertexAttribPointer(
    attrib, 3, GL_FLOAT, GL_FALSE, normStride, normOffset)
glEnableVertexAttribArray(attrib)

glBindVertexArray(0)  # unbind

If attribute names are consistent between shaders, you should be able to reuse the same code above, even if the vertex attribute layout locations differ between shaders. In some cases the shader may not accept one or more available attributes (eg. texture coordinates) that are available. Instead of writing multiple sub-routines for building VAOs to handle these permutations, simply check for attribute membership in the data returned by getAttribLocations:

attribLocations = getAttribLocations(myShader)
hasTexCoords = 'textureCoords' in attribLocations.keys()

# when binding attribute pointers
if hasTexCoords:
    attrib = attribLocations['textureCoords']
    glVertexAttribPointer(
        attrib, 2, GL_FLOAT, GL_FALSE, texCoordStride, texCoordOffset)
    glEnableVertexAttribArray(attrib)
psychopy.tools.gltools.createFBO(attachments=())[source]

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

Create 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)

# 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']

Using a 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)[source]

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

Attach an image to attachment points on the framebuffer:

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()[source]

Check if the currently bound framebuffer is complete.

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

Delete a framebuffer.

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

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

Blitting pixels from on FBO to another:

# 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(fbo)[source]

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

Using a framebuffer context manager:

# 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)[source]

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)[source]

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=())[source]

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

Creating a texture from an image file:

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=())[source]

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)[source]

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)[source]

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

Creating a vertex buffer object with vertex data:

# 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)

Drawing triangles using vertex buffer data:

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)[source]

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

Creating a VAO using VBOs:

vaoDesc = createVAO(vboVerts, vboTexCoords, vboNormals)

Draw the VAO, rendering the mesh:

drawVAO(vaoDesc, GL.GL_TRIANGLES)
psychopy.tools.gltools.drawVAO(vao, mode=4, flush=False)[source]

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

Creating a VAO and drawing it:

vaoDesc = createVAO(vboVerts, vboTexCoords, vboNormals)

# draw the VAO, renders the mesh
drawVAO(vaoDesc, GL.GL_TRIANGLES)
psychopy.tools.gltools.deleteVBO(vbo)[source]

Delete a Vertex Buffer Object (VBO).

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

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)[source]

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

Creating a new material with given properties:

# 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)[source]

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 a 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=())[source]

Create a point light source.

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

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.
psychopy.tools.gltools.setAmbientLight(color)[source]

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.

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)[source]

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

Loading a *.OBJ mode from file:

objModel = loadObjFile('/path/to/file.obj')

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

Drawing a mesh previously loaded:

# 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)[source]

Load a material library (*.mtl).

psychopy.tools.gltools.getIntegerv(parName)[source]

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)[source]

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)[source]

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()[source]

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)

Back to top