def IsUsable(self): """ Returns whether the program is usable. In other words, whether the OpenGl driver supports GLSL. """ if self._usable is None: # Not True nor False usable = getOpenGlCapable('2.0', 'anti-aliasing, the clim property, colormaps and 3D rendering') self._usable = bool(usable) # Make very sure its not None return self._usable
def IsUsable(self): """ Returns whether the program is usable. In other words, whether the OpenGl driver supports GLSL. """ if self._usable is None: # Not True nor False usable = getOpenGlCapable( '2.0', 'anti-aliasing, the clim property, colormaps and 3D rendering') self._usable = bool(usable) # Make very sure its not None return self._usable
def _DrawLines(self): # set stipple style if not self.ls in lineStyles: stipple = False else: stipple = lineStyles[self.ls] # if stipple and self.lw: gl.glEnable(gl.GL_LINE_STIPPLE) gl.glLineStipple(int(round(self.lw)), stipple) else: gl.glDisable(gl.GL_LINE_STIPPLE) # init vertex array gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointerf(self._points.data) # linepieces drawn on top of other should draw just fine. See issue #95 gl.glDepthFunc(gl.GL_LEQUAL) # init blending. Only use constant blendfactor when alpha<1 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if self._alpha1 < 1: #if len(self._points) < 1000: if getOpenGlCapable('1.4', 'transparant points and lines'): gl.glBlendFunc(gl.GL_CONSTANT_ALPHA, gl.GL_ONE_MINUS_CONSTANT_ALPHA) gl.glBlendColor(0.0, 0.0, 0.0, self._alpha1) gl.glDisable(gl.GL_DEPTH_TEST) # get color clr = getColor(self.lc) if clr and self._alpha1 > 0: # set width and color gl.glLineWidth(self.lw) gl.glColor3f(clr[0], clr[1], clr[2]) # draw method = gl.GL_LINE_STRIP if self.ls == '+': method = gl.GL_LINES gl.glDrawArrays(method, 0, len(self._points)) # flush! gl.glFlush() # clean up gl.glDisable(gl.GL_LINE_STIPPLE) gl.glLineStipple(int(round(self.lw)), int('1111111111111111', 2)) gl.glEnable(gl.GL_DEPTH_TEST) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDepthFunc(gl.GL_LESS)
def __init__(self): # ids self._programId = 0 self._shaderIds = [] # code for the shaders self._fragmentCode = '' self._vertexCode = '' # is usable? self._usable = True if not getOpenGlCapable('2.0', 'anti-aliasing, the clim property, colormaps and 3D rendering'): self._usable = False
def _DrawLines(self): # set stipple style if not self.ls in lineStyles: stipple = False else: stipple = lineStyles[self.ls] # if stipple and self.lw: gl.glEnable(gl.GL_LINE_STIPPLE) gl.glLineStipple(int(round(self.lw)), stipple) else: gl.glDisable(gl.GL_LINE_STIPPLE) # init vertex array gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointerf(self._points.data) # init blending. Only use constant blendfactor when alpha<1 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if self._alpha1<1: if getOpenGlCapable('1.4','transparant points and lines'): gl.glBlendFunc(gl.GL_CONSTANT_ALPHA, gl.GL_ONE_MINUS_CONSTANT_ALPHA) gl.glBlendColor(0.0,0.0,0.0, self._alpha1) gl.glDisable(gl.GL_DEPTH_TEST) # get color clr = getColor( self.lc ) if clr and self._alpha1>0: # set width and color gl.glLineWidth(self.lw) gl.glColor3f(clr[0], clr[1], clr[2]) # draw method = gl.GL_LINE_STRIP if self.ls == '+': method = gl.GL_LINES gl.glDrawArrays(method, 0, len(self._points)) # flush! gl.glFlush() # clean up gl.glDisable(gl.GL_LINE_STIPPLE) gl.glLineStipple(int(round(self.lw)), int('1111111111111111',2)) gl.glEnable(gl.GL_DEPTH_TEST) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
def __init__(self): # ids self._programId = 0 self._shaderIds = [] # code for the shaders self._fragmentCode = '' self._vertexCode = '' # is usable? self._usable = True if not getOpenGlCapable( '2.0', 'anti-aliasing, the clim property, colormaps and 3D rendering' ): self._usable = False
def Enable(self, texUnit=0): """ Enable(texUnit) Enable the texture, using the given texture unit (max 9). If necessary, will upload/update the texture in OpenGl memory now. If texUnit is -1, will not bind the texture. """ # Did we fail uploading texture last time? troubleLastTime = (self._uploadFlag==0) # If texture invalid, tell to upload, but only if we have a chance if self._texId == 0 or not gl.glIsTexture(self._texId): if not troubleLastTime: # Only if not in failure mode self._uploadFlag = abs(self._uploadFlag) # Store texture-Unit-id, and activate. Do before calling _setDataNow! if texUnit >= 0: self._texUnit = texUnit self._useTexUnit = getOpenGlCapable('1.3') if self._useTexUnit: gl.glActiveTexture( gl.GL_TEXTURE0 + texUnit ) # Opengl v1.3 # If we should upload/update, do that now. (SetData also sets the flag) if self._uploadFlag > 0: self._SetDataNow() # check if ok now if not gl.glIsTexture(self._texId): if not troubleLastTime: tmp = " (Hiding message for future draws.)" print "Warning enabling texture, the texture is not valid."+tmp return # Enable texturing, and bind to texture if texUnit >= 0: gl.glEnable(self._texType) gl.glBindTexture(self._texType, self._texId)
def Enable(self, texUnit=0): """ Enable(texUnit) Enable the texture, using the given texture unit (max 9). If necessary, will upload/update the texture in OpenGl memory now. If texUnit is -1, will not bind the texture. """ # Did we fail uploading texture last time? troubleLastTime = (self._uploadFlag == 0) # If texture invalid, tell to upload, but only if we have a chance if self._texId == 0 or not gl.glIsTexture(self._texId): if not troubleLastTime: # Only if not in failure mode self._uploadFlag = abs(self._uploadFlag) # Store texture-Unit-id, and activate. Do before calling _setDataNow! if texUnit >= 0: self._texUnit = texUnit self._useTexUnit = getOpenGlCapable('1.3') if self._useTexUnit: gl.glActiveTexture(gl.GL_TEXTURE0 + texUnit) # Opengl v1.3 # If we should upload/update, do that now. (SetData also sets the flag) if self._uploadFlag > 0: self._SetDataNow() # check if ok now if not gl.glIsTexture(self._texId): if not troubleLastTime: tmp = " (Hiding message for future draws.)" print "Warning enabling texture, the texture is not valid." + tmp return # Enable texturing, and bind to texture if texUnit >= 0: gl.glEnable(self._texType) gl.glBindTexture(self._texType, self._texId)
def shader(self): if self._shader is None: if not getOpenGlCapable('2.0', 'Antialiased text'): self._shader = self self.Enable = lambda: None self.Disable = lambda: None global TEX_SCALE TEX_SCALE = 1.5 # Make text more blurry else: # Create shader self._shader = Shader() # Set fragment code, vertex code is empty self._shader.vertex.Clear() fragment = ShaderCodePart('textaa', '', FRAGMENT_SHADER) self._shader.fragment.AddPart(fragment) # Set uniform shape = self.atlas.data.shape[:2] uniform_shape = [float(s) for s in reversed(list(shape))] self.shader.SetStaticUniform('shape', uniform_shape) return self._shader
def Create(self): """ Create an OpenGL texture from the data. """ # detemine now if we can use point sprites self._canUse = getOpenGlCapable( '2.0', 'point sprites (for advanced markers)') if not self._canUse: return # gl.glEnable(gl.GL_TEXTURE_2D) # make texture self._texId = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, self._texId) # set interpolation and extrapolation parameters tmp = gl.GL_NEAREST # gl.GL_NEAREST | gl.GL_LINEAR gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, tmp) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, tmp) # upload data shape = self._data.shape gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, shape[0], shape[1], 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, self._data)
def Create(self): """ Create an OpenGL texture from the data. """ # detemine now if we can use point sprites self._canUse = getOpenGlCapable('2.0', 'point sprites (for advanced markers)') if not self._canUse: return # gl.glEnable(gl.GL_TEXTURE_2D) # make texture self._texId = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, self._texId) # set interpolation and extrapolation parameters tmp = gl.GL_NEAREST # gl.GL_NEAREST | gl.GL_LINEAR gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, tmp) gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, tmp) # upload data shape = self._data.shape gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, shape[0], shape[1], 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, self._data)
def _SetDataNow(self): """ Make sure the data in self._dataRef is uploaded to OpenGl memory. If possible, update the data rather than create a new texture object. """ # Test whether padding to a factor of two is required needPadding = (abs(self._uploadFlag) == 2) needPadding = needPadding or not getOpenGlCapable('2.0') # Set flag in case of failure (set to success at the end) # If we tried without padding, we can still try with padding. # Note: In theory, getOpenGlCapable('2.0') should be enough to # determine if padding is required. However, bloody ATI drivers # sometimes need 2**n textures even if OpenGl > 2.0. (I've # encountered this with someones PC and verified that the current # solution solves this.) if needPadding: self._uploadFlag = 0 # Give up else: self._uploadFlag = 2 # Try with padding next time # Get data. if self._dataRef is None: return data = self._dataRef # older OpenGl versions do not know about 3D textures if self._ndim==3 and not getOpenGlCapable('1.2','3D textures'): return # Make singles if doubles (sadly opengl does not know about doubles) if data.dtype == np.float64: data = data.astype(np.float32) # dito for bools if data.dtype == np.bool: data = data.astype(np.uint8) # Determine type thetype = data.dtype.name if not thetype in dtypes: # this should not happen, since we concert incompatible types raise ValueError("Cannot convert datatype %s." % thetype) gltype = dtypes[thetype] # Determine format internalformat, format = self._GetFormat(data.shape) # Can we update or should we upload? if ( gl.glIsTexture(self._texId) and self._shape and (data.shape == self._shape) ): # We can update. # Bind to texture gl.glBindTexture(self._texType, self._texId) # update self._UpdateTexture(data, internalformat, format, gltype) else: # We should upload. # Remove any old data. self.DestroyGl() # Create texture object self._texId = gl.glGenTextures(1) # Bind to texture gl.glBindTexture(self._texType, self._texId) # Should we make the image a power of two? if needPadding: data2 = makePowerOfTwo(data, self._ndim) if data2 is not data: data = data2 print "Warning: the data was padded to make it a power of two." # test whether it fits, downsample if necessary ok, count = False, 0 while not ok and count<8: ok = self._TestUpload(data, internalformat,format,gltype) if not ok: #if count<2 and data.shape[0]<1000: # for testing data = downSample(data, self._ndim) count += 1 # give warning or error if count and not ok: raise MemoryError( "Could not upload texture to OpenGL, " + "even after 8 times downsampling.") elif count: print( "Warning: data was downscaled " + str(count) + " times to fit it in OpenGL memory." ) # upload! self._UploadTexture(data, internalformat, format, gltype) # keep reference of data shape (as loaded to opengl) self._shape = data.shape # flag success if needPadding: self._uploadFlag = -2 else: self._uploadFlag = -1
def _DrawPoints(self): # get colors (use color from edge or face if not present) clr1 = getColor(self.mc) clr2 = getColor(self.mec) # draw face or edge? drawFace = bool(self.mc) # if not ms or mw we would not get here drawEdge = self.mec and self.mew if not drawFace and not drawEdge: return # get figure f = self.GetFigure() if not f: return # init blending. Only use constant blendfactor when alpha<1 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if self._alpha1 < 1: if getOpenGlCapable('1.4', 'transparant points and lines'): gl.glBlendFunc(gl.GL_CONSTANT_ALPHA, gl.GL_ONE_MINUS_CONSTANT_ALPHA) gl.glBlendColor(0.0, 0.0, 0.0, self._alpha1) gl.glDisable(gl.GL_DEPTH_TEST) # init vertex array gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointerf(self._points.data) # points drawn on top of points should draw (because we draw # the face and edge seperately) gl.glDepthFunc(gl.GL_LEQUAL) # Enable alpha test, such that fragments with 0 alpha # will not update the z-buffer. gl.glEnable(gl.GL_ALPHA_TEST) gl.glAlphaFunc(gl.GL_GREATER, 0.01) if self.ms in ['o', '.', 's'] and not drawEdge: # Use standard OpenGL points, faster and anti-aliased # Pure filled points or squares always work. # choose style if self.ms == 's': gl.glDisable(gl.GL_POINT_SMOOTH) else: gl.glEnable(gl.GL_POINT_SMOOTH) # draw faces only if drawFace: gl.glColor3f(clr1[0], clr1[1], clr1[2]) gl.glPointSize(self.mw) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) elif self.ms in ['o', '.', 's'] and drawFace and self.alpha == 1: # Use standard OpenGL points, faster and anti-aliased # If alpha=1 and we have a filled marker, we can draw in two steps. # choose style if self.ms == 's': gl.glDisable(gl.GL_POINT_SMOOTH) else: gl.glEnable(gl.GL_POINT_SMOOTH) # draw edges if drawEdge: gl.glColor3f(clr2[0], clr2[1], clr2[2]) gl.glPointSize(self.mw + self.mew * 2) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # draw faces if drawFace: gl.glColor3f(clr1[0], clr1[1], clr1[2]) gl.glPointSize(self.mw) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) #elif self.alpha>0: else: # Use sprites # get sprites tmp = f._markerManager.GetSprites(self.ms, self.mw, self.mew) pSize, sprite1, sprite2 = tmp gl.glPointSize(pSize) # draw points for the edges if drawEdge: sprite2.Enable() gl.glColor3f(clr2[0], clr2[1], clr2[2]) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # draw points for the faces if drawFace: sprite1.Enable() gl.glColor3f(clr1[0], clr1[1], clr1[2]) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # disable sprites sprite1.Disable() # Could as well have used sprite2 # clean up gl.glDisable(gl.GL_ALPHA_TEST) gl.glEnable(gl.GL_DEPTH_TEST) gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDepthFunc(gl.GL_LESS) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
def _SetDataNow(self): """ Make sure the data in self._dataRef is uploaded to OpenGl memory. If possible, update the data rather than create a new texture object. """ # Test whether padding to a factor of two is required needPadding = (abs(self._uploadFlag) == 2) needPadding = needPadding or not getOpenGlCapable('2.0') # Set flag in case of failure (set to success at the end) # If we tried without padding, we can still try with padding. # Note: In theory, getOpenGlCapable('2.0') should be enough to # determine if padding is required. However, bloody ATI drivers # sometimes need 2**n textures even if OpenGl > 2.0. (I've # encountered this with someones PC and verified that the current # solution solves this.) if needPadding: self._uploadFlag = 0 # Give up else: self._uploadFlag = 2 # Try with padding next time # Get data. if self._dataRef is None: return data = self._dataRef # older OpenGl versions do not know about 3D textures if self._ndim == 3 and not getOpenGlCapable('1.2', '3D textures'): return # Make singles if doubles (sadly opengl does not know about doubles) if data.dtype == np.float64: data = data.astype(np.float32) # dito for bools if data.dtype == np.bool: data = data.astype(np.uint8) # Determine type thetype = data.dtype.name if not thetype in dtypes: # this should not happen, since we concert incompatible types raise ValueError("Cannot convert datatype %s." % thetype) gltype = dtypes[thetype] # Determine format internalformat, format = self._GetFormat(data.shape) # Can we update or should we upload? if (gl.glIsTexture(self._texId) and self._shape and (data.shape == self._shape)): # We can update. # Bind to texture gl.glBindTexture(self._texType, self._texId) # update self._UpdateTexture(data, internalformat, format, gltype) else: # We should upload. # Remove any old data. self.DestroyGl() # Create texture object self._texId = gl.glGenTextures(1) # Bind to texture gl.glBindTexture(self._texType, self._texId) # Should we make the image a power of two? if needPadding: data2 = makePowerOfTwo(data, self._ndim) if data2 is not data: data = data2 print "Warning: the data was padded to make it a power of two." # test whether it fits, downsample if necessary ok, count = False, 0 while not ok and count < 8: ok = self._TestUpload(data, internalformat, format, gltype) if not ok: #if count<2 and data.shape[0]<1000: # for testing data = downSample(data, self._ndim) count += 1 # give warning or error if count and not ok: raise MemoryError("Could not upload texture to OpenGL, " + "even after 8 times downsampling.") elif count: print("Warning: data was downscaled " + str(count) + " times to fit it in OpenGL memory.") # upload! self._UploadTexture(data, internalformat, format, gltype) # keep reference of data shape (as loaded to opengl) self._shape = data.shape # flag success if needPadding: self._uploadFlag = -2 else: self._uploadFlag = -1
def _DrawPoints(self): # get colors (use color from edge or face if not present) clr1 = getColor(self.mc) clr2 = getColor(self.mec) # draw face or edge? drawFace = bool(self.mc) # if not ms or mw we would not get here drawEdge = self.mec and self.mew if not drawFace and not drawEdge: return # get figure f = self.GetFigure() if not f: return # init blending. Only use constant blendfactor when alpha<1 gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if self._alpha1<1: if getOpenGlCapable('1.4','transparant points and lines'): gl.glBlendFunc(gl.GL_CONSTANT_ALPHA, gl.GL_ONE_MINUS_CONSTANT_ALPHA) gl.glBlendColor(0.0,0.0,0.0, self._alpha1) gl.glDisable(gl.GL_DEPTH_TEST) # init vertex array gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointerf(self._points.data) # points drawn on top of points should draw (because we draw # the face and edge seperately) gl.glDepthFunc(gl.GL_LEQUAL) # Enable alpha test, such that fragments with 0 alpha # will not update the z-buffer. gl.glEnable(gl.GL_ALPHA_TEST) gl.glAlphaFunc(gl.GL_GREATER, 0.01) if self.ms in ['o','.','s'] and not drawEdge: # Use standard OpenGL points, faster and anti-aliased # Pure filled points or squares always work. # choose style if self.ms == 's': gl.glDisable(gl.GL_POINT_SMOOTH) else: gl.glEnable(gl.GL_POINT_SMOOTH) # draw faces only if drawFace: gl.glColor3f(clr1[0],clr1[1],clr1[2]) gl.glPointSize(self.mw) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) elif self.ms in ['o','.','s'] and drawFace and self.alpha==1: # Use standard OpenGL points, faster and anti-aliased # If alpha=1 and we have a filled marker, we can draw in two steps. # choose style if self.ms == 's': gl.glDisable(gl.GL_POINT_SMOOTH) else: gl.glEnable(gl.GL_POINT_SMOOTH) # draw edges if drawEdge: gl.glColor3f(clr2[0],clr2[1],clr2[2]) gl.glPointSize(self.mw+self.mew*2) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # draw faces if drawFace: gl.glColor3f(clr1[0],clr1[1],clr1[2]) gl.glPointSize(self.mw) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) #elif self.alpha>0: else: # Use sprites # get sprites tmp = f._markerManager.GetSprites(self.ms, self.mw, self.mew) pSize, sprite1, sprite2 = tmp gl.glPointSize(pSize) # draw points for the edges if drawEdge: sprite2.Enable() gl.glColor3f(clr2[0],clr2[1],clr2[2]) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # draw points for the faces if drawFace: sprite1.Enable() gl.glColor3f(clr1[0],clr1[1],clr1[2]) gl.glDrawArrays(gl.GL_POINTS, 0, len(self._points)) # disable sprites sprite1.Disable() # Could as well have used sprite2 # clean up gl.glDisable(gl.GL_ALPHA_TEST) gl.glEnable(gl.GL_DEPTH_TEST) gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDepthFunc(gl.GL_LESS) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)