Skip to content
Snippets Groups Projects
Commit cea95d39 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Woo! ARB program parsing/dynamic parameter/attribute/texture binding

works. GLVolume, GLLabel and GLModel ported. All other things broken,
probably.
parent 9e5ecbea
No related branches found
No related tags found
No related merge requests found
...@@ -29,27 +29,24 @@ TEMP lutCoord; ...@@ -29,27 +29,24 @@ TEMP lutCoord;
TEMP invNumLabels; TEMP invNumLabels;
TEMP voxValue; TEMP voxValue;
PARAM imageShape = program.local[4]; PARAM imageShape = {{ param_imageShape }};
MOV invNumLabels, program.local[5]; MOV invNumLabels, {{ param_invNumLabels }};
PARAM outline = program.local[6]; PARAM outline = {{ param_outline }};
# This matrix scales the voxel value to # This matrix scales the voxel value to
# lie in a range which is appropriate to # lie in a range which is appropriate to
# the current display range # the current display range
PARAM voxValXform[4] = { program.local[0], PARAM voxValXform[4] = {{ param4_voxValXform }};
program.local[1],
program.local[2],
program.local[3] };
# retrieve the voxel coordinates, # retrieve the voxel coordinates,
# bail if they are are out of bounds # bail if they are are out of bounds
MOV voxCoord, fragment.texcoord[1]; MOV voxCoord, {{ varying_voxCoord }};
#pragma include test_in_bounds.prog #pragma include test_in_bounds.prog
# look up image voxel value # look up image voxel value
# from 3D image texture # from 3D image texture
TEX voxValue, fragment.texcoord[0], texture[0], 3D; TEX voxValue, {{ varying_texCoord }}, {{ texture_imageTexture }}, 3D;
# Scale the texture value # Scale the texture value
# to its original voxel value # to its original voxel value
...@@ -63,7 +60,7 @@ MUL lutCoord, lutCoord, invNumLabels; ...@@ -63,7 +60,7 @@ MUL lutCoord, lutCoord, invNumLabels;
# look up the appropriate colour # look up the appropriate colour
# in the 1D colour map texture # in the 1D colour map texture
TEX result.color, lutCoord.x, texture[1], 1D; TEX result.color, lutCoord.x, {{ texture_lutTexture }}, 1D;
# Test whether this fragment lies # Test whether this fragment lies
...@@ -74,7 +71,7 @@ TEMP val; ...@@ -74,7 +71,7 @@ TEMP val;
TEMP tol; TEMP tol;
TEMP offsets; TEMP offsets;
MOV coord, fragment.texcoord[0]; MOV coord, {{ varying_texCoord }};
MOV val, voxValue; MOV val, voxValue;
MOV tol, invNumLabels.x; MOV tol, invNumLabels.x;
MUL tol, tol, 0.001; MUL tol, tol, 0.001;
......
...@@ -14,24 +14,18 @@ defined in the :mod:`.gl14.glvolume_funcs` are re-used by this module. ...@@ -14,24 +14,18 @@ defined in the :mod:`.gl14.glvolume_funcs` are re-used by this module.
""" """
import numpy as np import numpy as np
import OpenGL.GL as gl
import OpenGL.raw.GL._types as gltypes
import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp
import fsl.fsleyes.gl.shaders as shaders import fsl.fsleyes.gl.shaders as shaders
import glvolume_funcs
import glvolume_funcs
def init(self): def init(self):
"""Calls the :func:`compileShaders` and :func:`updateShaderState` """Calls the :func:`compileShaders` and :func:`updateShaderState`
functions. functions.
""" """
self.vertexProgram = None
self.fragmentProgram = None self.shader = None
compileShaders( self) compileShaders( self)
updateShaderState(self) updateShaderState(self)
...@@ -39,48 +33,39 @@ def init(self): ...@@ -39,48 +33,39 @@ def init(self):
def destroy(self): def destroy(self):
"""Deletes handles to the vertex/fragment shader programs. """ """Deletes handles to the vertex/fragment shader programs. """
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram)) self.shader.delete()
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram)) self.shader = None
def compileShaders(self): def compileShaders(self):
"""Compiles the vertex and fragment shader programs used to render """Compiles the vertex and fragment shader programs used to render
:class:`.GLLabel` instances. :class:`.GLLabel` instances.
""" """
if self.vertexProgram is not None: if self.shader is not None:
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram)) self.shader.delete()
if self.fragmentProgram is not None: vertSrc = shaders.getVertexShader( 'glvolume')
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram)) fragSrc = shaders.getFragmentShader('gllabel')
textures = {
vertShaderSrc = shaders.getVertexShader( 'glvolume') 'imageTexture' : 0,
fragShaderSrc = shaders.getFragmentShader('gllabel') 'lutTexture' : 1,
}
vertexProgram, fragmentProgram = shaders.compilePrograms( self.shader = shaders.ARBPShader(vertSrc, fragSrc, textures)
vertShaderSrc, fragShaderSrc)
self.vertexProgram = vertexProgram
self.fragmentProgram = fragmentProgram
def updateShaderState(self): def updateShaderState(self):
"""Updates all shader program variables. """ """Updates all shader program variables. """
opts = self.displayOpts opts = self.displayOpts
# enable the vertex and fragment programs # enable the vertex and fragment programs
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB) self.shader.load()
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
self.vertexProgram)
arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
self.fragmentProgram)
voxValXform = self.imageTexture.voxValXform voxValXform = self.imageTexture.voxValXform
shape = list(self.image.shape[:3]) shape = list(self.image.shape[:3]) + [0]
offsets = opts.outlineWidth / \ offsets = opts.outlineWidth / \
np.array(self.image.shape[:3], dtype=np.float32) np.array(self.image.shape[:3], dtype=np.float32)
invNumLabels = 1.0 / (opts.lut.max() + 1) invNumLabels = 1.0 / (opts.lut.max() + 1)
if opts.transform == 'affine': if opts.transform == 'affine':
...@@ -92,14 +77,13 @@ def updateShaderState(self): ...@@ -92,14 +77,13 @@ def updateShaderState(self):
if opts.outline: offsets = [1] + list(offsets) if opts.outline: offsets = [1] + list(offsets)
else: offsets = [0] + list(offsets) else: offsets = [0] + list(offsets)
shaders.setVertexProgramVector( 0, shape + [0]) self.shader.setVertParam('imageShape', shape)
shaders.setFragmentProgramMatrix(0, voxValXform) self.shader.setFragParam('imageShape', shape)
shaders.setFragmentProgramVector(4, shape + [0]) self.shader.setFragParam('voxValXform', voxValXform)
shaders.setFragmentProgramVector(5, [invNumLabels, 0, 0, 0]) self.shader.setFragParam('invNumLabels', [invNumLabels, 0, 0, 0])
shaders.setFragmentProgramVector(6, offsets) self.shader.setFragParam('outline', offsets)
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB) self.shader.unload()
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
preDraw = glvolume_funcs.preDraw preDraw = glvolume_funcs.preDraw
......
...@@ -19,11 +19,11 @@ TEMP output; ...@@ -19,11 +19,11 @@ TEMP output;
# edge detection tolerance is # edge detection tolerance is
# 1 / 255 - a colour change of 1 bit # 1 / 255 - a colour change of 1 bit
PARAM tol = 0.00392156862745098; PARAM tol = 0.00392156862745098;
PARAM offsets = program.local[0]; PARAM offsets = {{ param_offsets }};
MOV coord, fragment.texcoord[0]; MOV coord, {{ varying_texCoord }};
TEX val, coord, texture[0], 2D; TEX val, coord, {{ texture_renderTexture }}, 2D;
#pragma include edge2D.prog #pragma include edge2D.prog
......
...@@ -9,12 +9,7 @@ class to render :class:`.Model` overlays in an OpenGL 1.4 compatible manner. ...@@ -9,12 +9,7 @@ class to render :class:`.Model` overlays in an OpenGL 1.4 compatible manner.
""" """
import OpenGL.GL as gl import fsl.fsleyes.gl.shaders as shaders
import OpenGL.raw.GL._types as gltypes
import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp
import fsl.fsleyes.gl.shaders as shaders
def compileShaders(self): def compileShaders(self):
...@@ -23,22 +18,20 @@ def compileShaders(self): ...@@ -23,22 +18,20 @@ def compileShaders(self):
instance. instance.
""" """
vertShaderSrc = shaders.getVertexShader( 'glmodel') vertSrc = shaders.getVertexShader( 'glmodel')
fragShaderSrc = shaders.getFragmentShader('glmodel') fragSrc = shaders.getFragmentShader('glmodel')
vertexProgram, fragmentProgram = shaders.compilePrograms( textures = {'renderTexture' : 0}
vertShaderSrc, fragShaderSrc)
self.vertexProgram = vertexProgram self.shader = shaders.ARBPShader(vertSrc, fragSrc, textures)
self.fragmentProgram = fragmentProgram
def destroy(self): def destroy(self):
"""Deletes the vertex/fragment shader programs that were compiled by """Deletes the vertex/fragment shader programs that were compiled by
:func:`compileShaders`. :func:`compileShaders`.
""" """
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram)) self.shader.delete()
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram)) self.shader = None
def updateShaders(self): def updateShaders(self):
...@@ -48,22 +41,15 @@ def updateShaders(self): ...@@ -48,22 +41,15 @@ def updateShaders(self):
offsets = self.getOutlineOffsets() offsets = self.getOutlineOffsets()
loadShaders(self) loadShaders(self)
shaders.setFragmentProgramVector(0, list(offsets) + [0, 0]) self.shader.setFragParam('offsets', list(offsets) + [0, 0])
unloadShaders(self) unloadShaders(self)
def loadShaders(self): def loadShaders(self):
"""Loads the :class:`.GLModel` vertex/fragment shader programs. """ """Loads the :class:`.GLModel` vertex/fragment shader programs. """
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB) self.shader.load()
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
self.vertexProgram)
arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
self.fragmentProgram)
def unloadShaders(self): def unloadShaders(self):
"""Un-loads the :class:`.GLModel` vertex/fragment shader programs. """ """Un-loads the :class:`.GLModel` vertex/fragment shader programs. """
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB) self.shader.unload()
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
...@@ -20,6 +20,6 @@ DP4 result.position.z, state.matrix.mvp.row[2], vertex.position; ...@@ -20,6 +20,6 @@ DP4 result.position.z, state.matrix.mvp.row[2], vertex.position;
DP4 result.position.w, state.matrix.mvp.row[3], vertex.position; DP4 result.position.w, state.matrix.mvp.row[3], vertex.position;
# Copy the vertex texture coordinate # Copy the vertex texture coordinate
MOV result.texcoord[0], vertex.texcoord[0]; MOV {{ varying_texCoord }}, {{ attr_texCoord }};
END END
...@@ -66,29 +66,26 @@ TEMP useNegCmap; ...@@ -66,29 +66,26 @@ TEMP useNegCmap;
TEMP negVoxValue; TEMP negVoxValue;
TEMP negClipValue; TEMP negClipValue;
PARAM imageShape = program.local[4]; PARAM imageShape = {{ param_imageShape }};
PARAM clipping = program.local[5]; PARAM clipping = {{ param_clipping }};
PARAM negCmap = program.local[6]; PARAM negCmap = {{ param_negCmap }};
# This matrix scales the voxel value to # This matrix scales the voxel value to
# lie in a range which is appropriate to # lie in a range which is appropriate to
# the current display range # the current display range
PARAM voxValXform[4] = { program.local[0], PARAM voxValXform[4] = {{ param4_voxValXform }};
program.local[1],
program.local[2],
program.local[3] };
# retrieve the voxel coordinates, # retrieve the voxel coordinates,
# bail if they are are out of bounds # bail if they are are out of bounds
MOV voxCoord, fragment.texcoord[1]; MOV voxCoord, {{ varying_voxCoord }};
#pragma include test_in_bounds.prog #pragma include test_in_bounds.prog
# look up image voxel value # look up image voxel value
# and clipping value from 3D # and clipping value from 3D
# image/clipping textures # image/clipping textures
TEX voxValue.x, fragment.texcoord[0], texture[0], 3D; TEX voxValue.x, {{ varying_texCoord }}, {{ texture_imageTexture }}, 3D;
TEX clipValue.x, fragment.texcoord[0], texture[3], 3D; TEX clipValue.x, {{ varying_texCoord }}, {{ texture_clipTexture }}, 3D;
# If the image texture is the clip # If the image texture is the clip
# texture, overwrite the clip value # texture, overwrite the clip value
...@@ -165,12 +162,12 @@ MAD voxValue, voxValue, voxValXform[0].x, voxValXform[3].x; ...@@ -165,12 +162,12 @@ MAD voxValue, voxValue, voxValXform[0].x, voxValXform[3].x;
# look up the appropriate colour # look up the appropriate colour
# in the 1D colour map texture # in the 1D colour map texture
TEX posColour, voxValue.x, texture[1], 1D; TEX posColour, voxValue.x, {{ texture_colourTexture }}, 1D;
TEX negColour, voxValue.x, texture[2], 1D; TEX negColour, voxValue.x, {{ texture_negColourTexture }}, 1D;
# useNegCmap is negative if the # useNegCmap is negative if the
# negative colour map should be # negative colour map should be
# used, positive otherwise. # used, positive otherwise.
CMP result.color, useNegCmap.x, negColour, posColour; CMP result.color, useNegCmap.x, negColour, posColour;
END END
\ No newline at end of file
...@@ -11,11 +11,8 @@ class to render :class:`.Image` overlays in an OpenGL 1.4 compatible manner. ...@@ -11,11 +11,8 @@ class to render :class:`.Image` overlays in an OpenGL 1.4 compatible manner.
import logging import logging
import numpy as np import numpy as np
import OpenGL.GL as gl import OpenGL.GL as gl
import OpenGL.raw.GL._types as gltypes
import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp
import fsl.utils.transform as transform import fsl.utils.transform as transform
import fsl.fsleyes.gl.shaders as shaders import fsl.fsleyes.gl.shaders as shaders
...@@ -27,8 +24,7 @@ log = logging.getLogger(__name__) ...@@ -27,8 +24,7 @@ log = logging.getLogger(__name__)
def init(self): def init(self):
"""Calls :func:`compileShaders` and :func:`updateShaderState`.""" """Calls :func:`compileShaders` and :func:`updateShaderState`."""
self.vertexProgram = None self.shader = None
self.fragmentProgram = None
compileShaders( self) compileShaders( self)
updateShaderState(self) updateShaderState(self)
...@@ -37,8 +33,8 @@ def init(self): ...@@ -37,8 +33,8 @@ def init(self):
def destroy(self): def destroy(self):
"""Deletes handles to the vertex/fragment programs.""" """Deletes handles to the vertex/fragment programs."""
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram)) self.shader.delete()
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram)) self.shader = None
def compileShaders(self): def compileShaders(self):
...@@ -49,20 +45,19 @@ def compileShaders(self): ...@@ -49,20 +45,19 @@ def compileShaders(self):
``framgentProgram`` respectively. ``framgentProgram`` respectively.
""" """
if self.vertexProgram is not None: if self.shader is not None:
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram)) self.shader.delete()
if self.fragmentProgram is not None:
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram))
vertShaderSrc = shaders.getVertexShader( 'glvolume')
fragShaderSrc = shaders.getFragmentShader('glvolume')
vertexProgram, fragmentProgram = shaders.compilePrograms( vertSrc = shaders.getVertexShader( 'glvolume')
vertShaderSrc, fragShaderSrc) fragSrc = shaders.getFragmentShader('glvolume')
textures = {
'imageTexture' : 0,
'colourTexture' : 1,
'negColourTexture' : 2,
'clipTexture' : 3
}
self.vertexProgram = vertexProgram self.shader = shaders.ARBPShader(vertSrc, fragSrc, textures)
self.fragmentProgram = fragmentProgram
def updateShaderState(self): def updateShaderState(self):
...@@ -70,13 +65,7 @@ def updateShaderState(self): ...@@ -70,13 +65,7 @@ def updateShaderState(self):
opts = self.displayOpts opts = self.displayOpts
# enable the vertex and fragment programs # enable the vertex and fragment programs
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB) self.shader.load()
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
self.vertexProgram)
arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
self.fragmentProgram)
# The voxValXform transformation turns # The voxValXform transformation turns
# an image texture value into a raw # an image texture value into a raw
...@@ -104,16 +93,19 @@ def updateShaderState(self): ...@@ -104,16 +93,19 @@ def updateShaderState(self):
clipLo = opts.clippingRange[0] * clipXform[0, 0] + clipXform[3, 0] clipLo = opts.clippingRange[0] * clipXform[0, 0] + clipXform[3, 0]
clipHi = opts.clippingRange[1] * clipXform[0, 0] + clipXform[3, 0] clipHi = opts.clippingRange[1] * clipXform[0, 0] + clipXform[3, 0]
texZero = 0.0 * imgXform[ 0, 0] + imgXform[ 3, 0] texZero = 0.0 * imgXform[ 0, 0] + imgXform[ 3, 0]
shaders.setVertexProgramVector( 0, shape + [0])
shaders.setFragmentProgramMatrix(0, voxValXform)
shaders.setFragmentProgramVector(4, shape + [0])
shaders.setFragmentProgramVector(5, [clipLo, clipHi, invClip, imageIsClip])
shaders.setFragmentProgramVector(6, [useNegCmap, texZero, 0, 0])
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB)
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB) shape = shape + [0]
clipping = [clipLo, clipHi, invClip, imageIsClip]
negCmap = [useNegCmap, texZero, 0, 0]
self.shader.setVertParam('imageShape', shape)
self.shader.setFragParam('voxValXform', voxValXform)
self.shader.setFragParam('imageShape', shape)
self.shader.setFragParam('clipping', clipping)
self.shader.setFragParam('negCmap', negCmap)
self.shader.unload()
def preDraw(self): def preDraw(self):
...@@ -121,34 +113,18 @@ def preDraw(self): ...@@ -121,34 +113,18 @@ def preDraw(self):
# enable drawing from a vertex array # enable drawing from a vertex array
gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
self.shader.load()
gl.glClientActiveTexture(gl.GL_TEXTURE0)
gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY)
# enable the vertex and fragment programs
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB)
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
self.vertexProgram)
arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
self.fragmentProgram)
def draw(self, zpos, xform=None): def draw(self, zpos, xform=None):
"""Draws a slice of the image at the given Z location. """ """Draws a slice of the image at the given Z location. """
vertices, voxCoords, texCoords = self.generateVertices(zpos, xform) vertices, voxCoords, texCoords = self.generateVertices(zpos, xform)
# Tex coords are texture 0 coords
# Vox coords are texture 1 coords
vertices = np.array(vertices, dtype=np.float32).ravel('C')
texCoords = np.array(texCoords, dtype=np.float32).ravel('C')
gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices) self.shader.setAttr('texCoord', texCoords)
gl.glClientActiveTexture(gl.GL_TEXTURE0) vertices = np.array(vertices, dtype=np.float32).ravel('C')
gl.glTexCoordPointer(3, gl.GL_FLOAT, 0, texCoords) gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
...@@ -168,14 +144,11 @@ def drawAll(self, zposes, xforms): ...@@ -168,14 +144,11 @@ def drawAll(self, zposes, xforms):
vertices[ i * 6: i * 6 + 6, :] = v vertices[ i * 6: i * 6 + 6, :] = v
texCoords[i * 6: i * 6 + 6, :] = tc texCoords[i * 6: i * 6 + 6, :] = tc
vertices = vertices .ravel('C') self.shader.setAttr('texCoord', texCoords)
texCoords = texCoords.ravel('C')
vertices = vertices.ravel('C')
gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices) gl.glVertexPointer(3, gl.GL_FLOAT, 0, vertices)
gl.glClientActiveTexture(gl.GL_TEXTURE0)
gl.glTexCoordPointer(3, gl.GL_FLOAT, 0, texCoords)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, nslices * 6) gl.glDrawArrays(gl.GL_TRIANGLES, 0, nslices * 6)
...@@ -183,10 +156,5 @@ def postDraw(self): ...@@ -183,10 +156,5 @@ def postDraw(self):
"""Cleans up the GL state after drawing from the given :class:`.GLVolume` """Cleans up the GL state after drawing from the given :class:`.GLVolume`
instance. instance.
""" """
gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
gl.glClientActiveTexture(gl.GL_TEXTURE0) self.shader.unload()
gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY)
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB)
...@@ -6,17 +6,18 @@ ...@@ -6,17 +6,18 @@
# passes the corresponding voxel and texture coordinates through to the # passes the corresponding voxel and texture coordinates through to the
# fragment program. # fragment program.
# #
# Inputs: # Input parameters:
# vertex.texcoord[0] - Texture coordinates # imageShape - image shape
# program.local[0] - image shape #
# # Input attributes:
# texCoord - Texture coordinates
# #
# Outputs: # Outputs:
# result.texcoord[0] - Texture coordinates # result.texcoord[0] - Texture coordinates
# result.texcoord[1] - Voxel coordinates # result.texcoord[1] - Voxel coordinates
# #
PARAM imageShape = program.local[0]; PARAM imageShape = {{ param_imageShape }};
TEMP voxCoord; TEMP voxCoord;
...@@ -26,12 +27,12 @@ DP4 result.position.y, state.matrix.mvp.row[1], vertex.position; ...@@ -26,12 +27,12 @@ DP4 result.position.y, state.matrix.mvp.row[1], vertex.position;
DP4 result.position.z, state.matrix.mvp.row[2], vertex.position; DP4 result.position.z, state.matrix.mvp.row[2], vertex.position;
DP4 result.position.w, state.matrix.mvp.row[3], vertex.position; DP4 result.position.w, state.matrix.mvp.row[3], vertex.position;
MOV result.texcoord[0], vertex.texcoord[0]; # Transform the texture coordinates
# into voxel coordinates
# Transform the texture coordinates into voxel coordinates MOV voxCoord, {{ attr_texCoord }};
MOV voxCoord, vertex.texcoord[0];
MUL voxCoord, voxCoord, imageShape; MUL voxCoord, voxCoord, imageShape;
MOV result.texcoord[1], voxCoord; MOV {{ varying_texCoord }}, {{ attr_texCoord }};
MOV {{ varying_voxCoord }}, voxCoord;
END END
\ No newline at end of file
...@@ -7,127 +7,19 @@ ...@@ -7,127 +7,19 @@
import logging import logging
import os.path as op import os.path as op
import fsl.fsleyes.gl as fslgl import fsl.fsleyes.gl as fslgl
import glsl.parse as glslparse import glsl.program as glslprogram
import glsl.program as glslprogram import arbp.program as arbpprogram
import arbp.parse as arbpparse
import arbp.program as arbpprogram
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
GLSLShader = glslprogram.GLSLShader GLSLShader = glslprogram.GLSLShader
ARBPShaer = arbpprogram.ARBPShader ARBPShader = arbpprogram.ARBPShader
parseGLSL = glslparse .parseGLSL
parseARBP = arbpparse .parseARBP
def setVertexProgramVector(index, vector):
"""Convenience function which sets the vertex program local parameter
at the given index to the given 4 component vector.
"""
import OpenGL.GL.ARB.vertex_program as arbvp
arbvp.glProgramLocalParameter4fARB(
arbvp.GL_VERTEX_PROGRAM_ARB, index, *vector)
def setVertexProgramMatrix(index, matrix):
"""Convenience function which sets four vertex program local parameters,
starting at the given index, to the given ``4*4`` matrix.
"""
import OpenGL.GL.ARB.vertex_program as arbvp
for i, row in enumerate(matrix):
arbvp.glProgramLocalParameter4fARB(
arbvp.GL_VERTEX_PROGRAM_ARB, i + index,
row[0], row[1], row[2], row[3])
def setFragmentProgramVector(index, vector):
"""Convenience function which sets the fragment program local parameter
at the given index to the given 4 component vector.
"""
import OpenGL.GL.ARB.fragment_program as arbfp
arbfp.glProgramLocalParameter4fARB(
arbfp.GL_FRAGMENT_PROGRAM_ARB, index, *vector)
def setFragmentProgramMatrix(index, matrix):
"""Convenience function which sets four fragment program local parameters,
starting at the given index, to the given ``4*4`` matrix.
"""
import OpenGL.GL.ARB.fragment_program as arbfp
for i, row in enumerate(matrix):
arbfp.glProgramLocalParameter4fARB(
arbfp.GL_FRAGMENT_PROGRAM_ARB, i + index,
row[0], row[1], row[2], row[3])
def compilePrograms(vertexProgramSrc, fragmentProgramSrc):
"""Compiles the given vertex and fragment programs (written according
to the ``ARB_vertex_program`` and ``ARB_fragment_program`` extensions),
and returns references to the compiled programs.
"""
import OpenGL.GL as gl
import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB)
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
fragmentProgram = arbfp.glGenProgramsARB(1)
vertexProgram = arbvp.glGenProgramsARB(1)
# vertex program
try:
arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
vertexProgram)
arbvp.glProgramStringARB(arbvp.GL_VERTEX_PROGRAM_ARB,
arbvp.GL_PROGRAM_FORMAT_ASCII_ARB,
len(vertexProgramSrc),
vertexProgramSrc)
except:
position = gl.glGetIntegerv(arbvp.GL_PROGRAM_ERROR_POSITION_ARB)
message = gl.glGetString( arbvp.GL_PROGRAM_ERROR_STRING_ARB)
raise RuntimeError('Error compiling vertex program '
'({}): {}'.format(position, message))
# fragment program
try:
arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
fragmentProgram)
arbfp.glProgramStringARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
arbfp.GL_PROGRAM_FORMAT_ASCII_ARB,
len(fragmentProgramSrc),
fragmentProgramSrc)
except:
position = gl.glGetIntegerv(arbfp.GL_PROGRAM_ERROR_POSITION_ARB)
message = gl.glGetString( arbfp.GL_PROGRAM_ERROR_STRING_ARB)
raise RuntimeError('Error compiling fragment program '
'({}): {}'.format(position, message))
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB)
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
return vertexProgram, fragmentProgram
def getVertexShader(prefix): def getVertexShader(prefix):
......
...@@ -50,31 +50,37 @@ def parseARBP(vertSrc, fragSrc): ...@@ -50,31 +50,37 @@ def parseARBP(vertSrc, fragSrc):
'varying' : vVaryings} 'varying' : vVaryings}
def fillARBP(vertSrc, fragSrc, vertParams, fragParams, textures, attrs): def fillARBP(vertSrc,
fragSrc,
vertParams,
vertParamLens,
fragParams,
fragParamLens,
textures,
attrs):
if vertParams is None: vertParams = {}
if fragParams is None: fragParams = {}
if textures is None: textures = {}
if attrs is None: attrs = {}
vertVars = _findDeclaredVariables(vertSrc) vertVars = _findDeclaredVariables(vertSrc)
fragVars = _findDeclaredVariables(fragSrc) fragVars = _findDeclaredVariables(fragSrc)
_checkVariableValidity( _checkVariableValidity(
vertVars, fragVars, vertParams, fragParams, textures, attrs) vertVars, fragVars, vertParams, fragParams, textures, attrs)
for name, (number, length) in vertParams.items(): for name, number in vertParams.items():
length = vertParamLens[name]
if length == 1: name = 'param_{}' .format(name) if length == 1: name = 'param_{}' .format(name)
else: name = 'param{}_{}'.format(name, length) else: name = 'param{}_{}'.format(name, length)
vertParams[name] = _param(number, length) vertParams[name] = _param(number, length)
for name, (number, length) in fragParams.items(): for name, number in fragParams.items():
length = fragParamLens[name]
if length == 1: name = 'param_{}' .format(name) if length == 1: name = 'param_{}' .format(name)
else: name = 'param{}_{}'.format(name, length) else: name = 'param{}_{}'.format(length, name)
fragParams[name] = _param(number, length) fragParams[name] = _param(number, length)
textures = {'texture_{}'.format(n) : _texture(v) textures = {'texture_{}'.format(n) : _texture(v)
...@@ -195,7 +201,7 @@ def _param(number, length): ...@@ -195,7 +201,7 @@ def _param(number, length):
bits = ['program.local[{}]'.format(n) for n in range(number, bits = ['program.local[{}]'.format(n) for n in range(number,
number + length)] number + length)]
return '{{ {} }}'.format(','.join(bits)) return '{{ {} }}'.format(', '.join(bits))
def _texture(number): def _texture(number):
......
...@@ -7,35 +7,175 @@ ...@@ -7,35 +7,175 @@
import logging import logging
import numpy as np
import OpenGL.GL as gl import OpenGL.GL as gl
import OpenGL.raw.GL._types as gltypes import OpenGL.raw.GL._types as gltypes
import OpenGL.GL.ARB.fragment_program as arbfp import OpenGL.GL.ARB.fragment_program as arbfp
import OpenGL.GL.ARB.vertex_program as arbvp import OpenGL.GL.ARB.vertex_program as arbvp
import parse
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class ARBPShader(object): class ARBPShader(object):
def __init__(self, def __init__(self, vertSrc, fragSrc, textureMap=None):
vertSrc,
fragSrc, decs = parse.parseARBP(vertSrc, fragSrc)
paramMap=None,
textureMap=None, vParams = decs['vertParam']
vertAttMap=None): fParams = decs['fragParam']
if len(vParams) > 0: vParams, vLens = zip(*vParams)
else: vParams, vLens = [], []
if len(fParams) > 0: fParams, fLens = zip(*fParams)
else: fParams, fLens = [], []
vLens = {name : length for name, length in zip(vParams, vLens)}
fLens = {name : length for name, length in zip(fParams, fLens)}
self.vertParams = vParams
self.vertParamLens = vLens
self.fragParams = fParams
self.fragParamLens = fLens
self.textures = decs['texture']
self.attrs = decs['attr']
poses = self.__generatePositions(textureMap)
vpPoses, fpPoses, texPoses, attrPoses = poses
self.vertParamPositions = vpPoses
self.fragParamPositions = fpPoses
self.texturePositions = texPoses
self.attrPositions = attrPoses
vertSrc, fragSrc = parse.fillARBP(vertSrc,
fragSrc,
self.vertParamPositions,
self.vertParamLens,
self.fragParamPositions,
self.fragParamLens,
self.texturePositions,
self.attrPositions)
vp, fp = self.__compile(vertSrc, fragSrc)
self.vertexProgram = vp
self.fragmentProgram = fp
self.__vertexProgram = None def delete(self):
self.__fragmentProgram = None arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.vertexProgram))
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.fragmentProgram))
if textureMap is None: textureMap = {}
if paramMap is None: paramMap = {}
if vertAttMap is None: vertAttMap = {}
def load(self):
gl.glEnable(arbvp.GL_VERTEX_PROGRAM_ARB)
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
def delete(self): arbvp.glBindProgramARB(arbvp.GL_VERTEX_PROGRAM_ARB,
arbvp.glDeleteProgramsARB(1, gltypes.GLuint(self.__vertexProgram)) self.vertexProgram)
arbfp.glDeleteProgramsARB(1, gltypes.GLuint(self.__fragmentProgram)) arbfp.glBindProgramARB(arbfp.GL_FRAGMENT_PROGRAM_ARB,
self.fragmentProgram)
for attr in self.attrs:
texUnit = self.__getAttrTexUnit(attr)
gl.glClientActiveTexture(texUnit)
gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY)
def unload(self):
gl.glDisable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
gl.glDisable(arbvp.GL_VERTEX_PROGRAM_ARB)
for attr in self.attrs:
texUnit = self.__getAttrTexUnit(attr)
gl.glClientActiveTexture(texUnit)
gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY)
def setVertParam(self, name, value):
pos = self.vertParamPositions[name]
value = np.array(value, dtype=np.float32).reshape((-1, 4))
for i, row in enumerate(value):
arbvp.glProgramLocalParameter4fARB(
arbvp.GL_VERTEX_PROGRAM_ARB, pos + i,
row[0], row[1], row[2], row[3])
def setFragParam(self, name, value):
pos = self.fragParamPositions[name]
value = np.array(value, dtype=np.float32).reshape((-1, 4))
for i, row in enumerate(value):
arbfp.glProgramLocalParameter4fARB(
arbfp.GL_FRAGMENT_PROGRAM_ARB, pos + i,
row[0], row[1], row[2], row[3])
def setAttr(self, name, value):
texUnit = self.__getAttrTexUnit(name)
size = value.shape[1]
value = np.array(value, dtype=np.float32)
value = value.ravel('C')
gl.glClientActiveTexture(texUnit)
gl.glTexCoordPointer(size, gl.GL_FLOAT, 0, value)
def __getAttrTexUnit(self, attr):
pos = self.attrPositions[attr]
texUnit = 'GL_TEXTURE{}'.format(pos)
texUnit = getattr(gl, texUnit)
return texUnit
def __generatePositions(self, textureMap=None):
vpPoses = {}
fpPoses = {}
texPoses = {}
attrPoses = {}
# Vertex parameters
pos = 0
for name in self.vertParams:
vpPoses[name] = pos
pos += self.vertParamLens[name]
# Fragment parameters
pos = 0
for name in self.fragParams:
fpPoses[name] = pos
pos += self.fragParamLens[name]
# Vertex attributes
for i, name in enumerate(self.attrs):
attrPoses[name] = i
# Texture positions. If the caller did
# not provide a texture map in __init__,
# we'll generate some positions.
if textureMap is None:
names = self.textures
poses = range(len(names))
texPoses = {n : p for n, p in zip(names, poses)}
else:
texPoses = dict(textureMap)
return vpPoses, fpPoses, texPoses, attrPoses
def __compile(self, vertSrc, fragSrc): def __compile(self, vertSrc, fragSrc):
...@@ -47,7 +187,12 @@ class ARBPShader(object): ...@@ -47,7 +187,12 @@ class ARBPShader(object):
gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB) gl.glEnable(arbfp.GL_FRAGMENT_PROGRAM_ARB)
fragProg = arbfp.glGenProgramsARB(1) fragProg = arbfp.glGenProgramsARB(1)
vertProg = arbvp.glGenProgramsARB(1) vertProg = arbvp.glGenProgramsARB(1)
# Make sure the source is plain
# ASCII - not unicode
vertSrc = str(vertSrc)
fragSrc = str(fragSrc)
# vertex program # vertex program
try: try:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment