Source code for fsleyes.gl.gl21.glmesh_funcs

#
# glmesh_funcs.py - OpenGL 2.1 functions used by the GLMesh class.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides functions which are used by the :class:`.GLMesh`
class to render :class:`.Mesh` overlays in an OpenGL 2.1 compatible
manner.

A :class:`.GLSLShader` is used to manage the ``glmesh`` vertex/fragment
shader programs.
"""


import OpenGL.GL as gl

import fsl.transform.affine as affine
import fsleyes.gl.shaders   as shaders


[docs]def compileShaders(self): """Loads the ``glmesh`` vertex/fragment shader source and creates :class:`.GLSLShader` instance(s). """ if self.threedee: flatVertSrc = shaders.getVertexShader( 'glmesh_3d_flat') flatFragSrc = shaders.getFragmentShader('glmesh_3d_flat') dataVertSrc = shaders.getVertexShader( 'glmesh_3d_data') dataFragSrc = shaders.getFragmentShader('glmesh_3d_data') self.flatShader = shaders.GLSLShader(flatVertSrc, flatFragSrc, indexed=True) self.dataShader = shaders.GLSLShader(dataVertSrc, dataFragSrc, indexed=True) else: vertSrc = shaders.getVertexShader( 'glmesh_2d_data') fragSrc = shaders.getFragmentShader('glmesh_2d_data') self.dataShader = shaders.GLSLShader(vertSrc, fragSrc)
[docs]def updateShaderState(self, **kwargs): """Updates the shader program according to the current :class:`.MeshOpts`` configuration. """ dopts = self.opts dshader = self.dataShader fshader = self.flatShader dshader.load() dshader.set('cmap', 0) dshader.set('negCmap', 1) dshader.set('useNegCmap', kwargs['useNegCmap']) dshader.set('cmapXform', kwargs['cmapXform']) dshader.set('flatColour', kwargs['flatColour']) dshader.set('invertClip', dopts.invertClipping) dshader.set('discardClipped', dopts.discardClipped) dshader.set('modulateAlpha', dopts.modulateAlpha) dshader.set('modScale', kwargs['modScale']) dshader.set('modOffset', kwargs['modOffset']) dshader.set('clipLow', dopts.clippingRange.xlo) dshader.set('clipHigh', dopts.clippingRange.xhi) if self.threedee: dshader.setAtt('vertex', self.vertices) dshader.setAtt('normal', self.normals) vdata = self.getVertexData('vertex') mdata = self.getVertexData('modulate') # if modulate data is not set, # we use the vertex data if mdata is None: mdata = vdata if vdata is not None: dshader.setAtt('vertexData', vdata.ravel('C')) if mdata is not None: dshader.setAtt('modulateData', mdata.ravel('C')) dshader.setIndices(self.indices) dshader.unload() if self.threedee: fshader.load() fshader.set('colour', kwargs['flatColour']) fshader.setAtt('vertex', self.vertices) fshader.setAtt('normal', self.normals) fshader.setIndices(self.indices) fshader.unload()
[docs]def preDraw(self): """Must be called before :func:`draw`. Loads the appropriate shader program. """ flat = self.opts.vertexData is None if flat: shader = self.flatShader else: shader = self.dataShader self.activeShader = shader shader.load()
[docs]def draw(self, glType, vertices, indices=None, normals=None, vdata=None, mdata=None): """Called for 3D meshes, and when :attr:`.MeshOpts.vertexData` is not ``None``. Loads and runs the shader program. :arg glType: The OpenGL primitive type. :arg vertices: ``(n, 3)`` array containing the line vertices to draw. :arg indices: Indices into the ``vertices`` array. If not provided, ``glDrawArrays`` is used. :arg normals: Vertex normals. :arg vdata: ``(n, )`` array containing data for each vertex. :arg mdata: ``(n, )`` array containing alpha modulation data for each vertex. """ canvas = self.canvas shader = self.activeShader # for 3D, shader attributes are # configured in updateShaderState if self.threedee: vertices = None normals = None vdata = None mdata = None if vertices is not None: shader.setAtt('vertex', vertices) if normals is not None: shader.setAtt('normal', normals) if vdata is not None: shader.setAtt('vertexData', vdata) if mdata is not None: shader.setAtt('modulateData', mdata) if self.threedee: lightPos = affine.transform(canvas.lightPos, canvas.viewMatrix) shader.set('lighting', canvas.opts.light) shader.set('lightPos', lightPos) shader.loadAtts() if indices is None: gl.glDrawArrays(glType, 0, vertices.shape[0]) else: nverts = indices.shape[0] if self.threedee: indices = None gl.glDrawElements(glType, nverts, gl.GL_UNSIGNED_INT, indices)
[docs]def postDraw(self): """Must be called after :func:`draw`. Unloads shaders, and unbinds textures. """ shader = self.activeShader shader.unloadAtts() shader.unload() self.activeShader = None