예제 #1
0
파일: grid.py 프로젝트: changcunyuan/gl-agg
class Grid(object):

    def __init__(self,
                 major_lines        = (1.00, 1.00, 0.75),
                 major_lines_color  = (0.75, 0.75, 0.75, 1.00),
                 major_ticks        = (5.00, 5.00, 1.50),
                 major_ticks_color  = (0.00, 0.00, 0.00, 1.00),
                 minor_lines        = (0.10, 0.10, 0.25),
                 minor_lines_color  = (0.75, 0.75, 0.75, 1.00),
                 minor_ticks        = (2.50, 2.50, 1.00),
                 minor_ticks_color  = (0.00, 0.00, 0.00, 1.00) ):
        self._major_lines          = np.array(major_lines)
        self._major_lines_color    = np.array(major_lines_color)
        self._major_ticks          = np.array(major_ticks)
        self._major_ticks_color    = np.array(major_ticks_color)
        self._minor_lines          = np.array(minor_lines)
        self._minor_lines_color    = np.array(minor_lines_color)
        self._minor_ticks          = np.array(minor_ticks)
        self._minor_ticks_color    = np.array(minor_ticks_color)

        vert = open('./grid.vert').read()
        frag = open('./grid.frag').read()
        self._shader = Shader(vert,frag)
        self._transform = 0.0,0.0,100.0,0.0

        w,h = 512,512
        vertices = np.array( [ ((0, 0), (0,0)),
                               ((w, 0), (w,0)),
                               ((w, h), (w,h)),
                               ((0, h), (0,h)) ],
                             dtype = [('position','f4',2), ('tex_coord','f4',2)] )
        vertices['position'] += .315,.315
        indices = np.array( [0,1,2, 0,2,3 ], dtype=np.uint32 )
        self._buffer = VertexBuffer(vertices,indices)


    def set_transforms(self, transforms):
        """ """

        self._transform = transforms


    def update(self):
        """ """

        _,_,w,h = gl.glGetIntegerv(gl.GL_VIEWPORT)
        self._buffer.vertices['position'][0] = 0, 0
        self._buffer.vertices['position'][1] = w, 0
        self._buffer.vertices['position'][2] = w, h
        self._buffer.vertices['position'][3] = 0, h
        self._buffer.vertices['position'] += .315, .315
        self._buffer.vertices['tex_coord'][0] = 0, 0
        self._buffer.vertices['tex_coord'][1] = w, 0
        self._buffer.vertices['tex_coord'][2] = w, h
        self._buffer.vertices['tex_coord'][3] = 0, h
        self._buffer.upload()


    def draw(self):

        x,y,scale,rotation = self._transform
        _,_,w,h = gl.glGetIntegerv(gl.GL_VIEWPORT)

        shader = self._shader
        shader.bind()
        shader.uniformf( 'size',               w,h)
        shader.uniformf( 'offset',             x,y)

        x,y,t   = self._major_lines
        r,g,b,a = self._major_lines_color
        shader.uniformf( 'major_lines',        x*scale, y*scale, max(t,1.0) )
        shader.uniformf( 'major_lines_color',  r,g,b,a*min(t,1.0) )

        x,y,t   = self._major_ticks
        r,g,b,a = self._major_ticks_color
        shader.uniformf( 'major_ticks',        x,y,max(t,1.0) )
        shader.uniformf( 'major_ticks_color',  r,g,b,a*min(t,1.0) )

        x,y,t   = self._minor_lines
        r,g,b,a = self._minor_lines_color
        shader.uniformf( 'minor_lines',        x*scale, y*scale, max(t,1.0) )
        shader.uniformf( 'minor_lines_color',  r,g,b,a*min(t,1.0) )

        x,y,t   = self._minor_ticks
        r,g,b,a = self._minor_ticks_color
        shader.uniformf( 'minor_ticks',        x,y,max(t,1.0) )
        shader.uniformf( 'minor_ticks_color',  r,g,b,a*min(t,1.0) )

        self._buffer.draw( gl.GL_TRIANGLES )
        shader.unbind()
예제 #2
0
파일: collection.py 프로젝트: x2nie/gl-agg
class Collection(object):

    join = {'miter': 0, 'round': 1, 'bevel': 2}

    caps = {
        '': 0,
        'none': 0,
        '.': 0,
        'round': 1,
        ')': 1,
        '(': 1,
        'o': 1,
        'triangle in': 2,
        '<': 2,
        'triangle out': 3,
        '>': 3,
        'square': 4,
        '=': 4,
        'butt': 4,
        '|': 5
    }

    # ---------------------------------
    def __init__(self, vtype, utype):
        self.dash_atlas = None

        # Convert types to lists (in case they were already dtypes) such that
        # we can append new fields
        vtype = eval(str(np.dtype(vtype)))
        utype = eval(str(np.dtype(utype)))

        # We add a uniform index to access uniform data from texture
        vtype.append(('a_index', 'f4'))

        # Check if given utype is made of float32 only
        rutype = dtype_reduce(utype)
        if type(rutype[0]) is not str or rutype[2] != 'float32':
            raise CollectionError(
                "Uniform type cannot de reduced to float32 only")
        else:
            count = rutype[1]
            size = count // 4
            if count % 4:
                size += 1
                utype.append(('unnused', 'f4', size * 4 - count))
            count = size * 4
            self.utype = utype
        self._vbuffer = VertexBuffer(vtype)
        self._ubuffer = DynamicBuffer(utype)
        self._ubuffer_id = 0
        self._ubuffer_shape = [0, count]

        self._dirty = True

    # ---------------------------------
    def __len__(self):
        return len(self._vbuffer)

    # ---------------------------------
    def __getitem__(self, key):
        V = self._vbuffer.vertices[key]
        I = self._vbuffer.indices[key]
        U = self._ubuffer[key]
        return Item(self, key, V, I, U)

    # ---------------------------------
    def __delitem__(self, key):
        start, end = self._vbuffer.vertices.range(key)
        del self._vbuffer[key]
        del self._ubuffer[key]
        self._vbuffer.vertices.data['a_index'][start:] -= 1
        self._vbuffer._dirty = True
        self._dirty = True

    # ---------------------------------
    def get_vertices(self):
        return self._vbuffer.vertices

    vertices = property(get_vertices)

    # ---------------------------------
    def get_indices(self):
        return self._vbuffer.indices

    indices = property(get_indices)

    # ---------------------------------
    def get_uniforms(self):
        return self._ubuffer

    uniforms = property(get_uniforms)

    # ---------------------------------
    def __getattr__(self, name):
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self, '_ubuffer')
            if name in buffer.dtype.names:
                return buffer.data[name]
        return object.__getattribute__(self, name)

    # ---------------------------------
    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self, '_ubuffer')
            if name in buffer.dtype.names:
                buffer.data[name] = value
                # buffer._dirty = True
                object.__setattr__(self, '_dirty', True)
        object.__setattr__(self, name, value)

    # ---------------------------------
    def clear(self):
        self._vbuffer.clear()
        self._ubuffer.clear()
        self._dirty = True

    # ---------------------------------
    def append(self, vertices, indices, uniforms):
        vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype)
        indices = np.array(indices).astype(self._vbuffer.indices.dtype)
        uniforms = np.array(uniforms).astype(self._ubuffer.dtype)
        vertices['a_index'] = len(self)
        self._vbuffer.append(vertices, indices)
        self._ubuffer.append(uniforms)
        self._ubuffer_shape[0] = len(self)
        self._dirty = True

    # ---------------------------------
    def upload(self):

        if not self._dirty:
            return

        self._vbuffer.upload()

        gl.glActiveTexture(gl.GL_TEXTURE0)
        data = self._ubuffer.data.view(np.float32)
        shape = self._ubuffer_shape
        if not self._ubuffer_id:
            self._ubuffer_id = gl.glGenTextures(1)

            gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id)
            gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
            gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER,
                               gl.GL_NEAREST)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER,
                               gl.GL_NEAREST)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S,
                               gl.GL_CLAMP_TO_EDGE)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T,
                               gl.GL_CLAMP_TO_EDGE)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0)
            gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1] // 4,
                            shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data)

        gl.glActiveTexture(gl.GL_TEXTURE0)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id)
        gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F, shape[1] // 4,
                        shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data)
        #gl.glTexSubImage2D( gl.GL_TEXTURE_2D,0, 0, 0, shape[1]//4, shape[0],
        #                    gl.GL_RGBA, gl.GL_FLOAT, data);
        self._dirty = False

    # ---------------------------------
    def bake(self, vertices):
        raise NotImplemented

    # ---------------------------------
    def draw(self):
        if self._dirty:
            self.upload()

        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glEnable(gl.GL_BLEND)
        _, _, width, height = gl.glGetIntegerv(gl.GL_VIEWPORT)
        P = orthographic(0, width, 0, height, -1, +1)
        V = np.eye(4).astype(np.float32)
        M = np.eye(4).astype(np.float32)

        shader = self.shader
        shader.bind()
        gl.glActiveTexture(gl.GL_TEXTURE0)
        shader.uniformi('u_uniforms', 0)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self._ubuffer_id)
        if self.dash_atlas:
            gl.glActiveTexture(gl.GL_TEXTURE1)
            shader.uniformi('u_dash_atlas', 1)
            gl.glBindTexture(gl.GL_TEXTURE_2D, self.dash_atlas.texture_id)
        shader.uniform_matrixf('u_M', M)
        shader.uniform_matrixf('u_V', V)
        shader.uniform_matrixf('u_P', P)
        shape = self._ubuffer_shape
        shader.uniformf('u_uniforms_shape', shape[1] // 4, shape[0])
        self._vbuffer.draw()
        shader.unbind()
예제 #3
0
class Collection(object):

    join = { 'miter' : 0,
             'round' : 1,
             'bevel' : 2 }

    caps = { ''             : 0,
             'none'         : 0,
             '.'            : 0,
             'round'        : 1,
             ')'            : 1,
             '('            : 1,
             'o'            : 1,
             'triangle in'  : 2,
             '<'            : 2,
             'triangle out' : 3,
             '>'            : 3,
             'square'       : 4,
             '='            : 4,
             'butt'         : 4,
             '|'            : 5 }


    # ---------------------------------
    def __init__(self, vtype, utype):
        self.dash_atlas = None

        # Convert types to lists (in case they were already dtypes) such that
        # we can append new fields
        vtype = eval(str(np.dtype(vtype)))
        utype = eval(str(np.dtype(utype)))

        # We add a uniform index to access uniform data from texture
        vtype.append( ('a_index', 'f4') )

        # Check if given utype is made of float32 only
        rutype = dtype_reduce(utype)
        if type(rutype[0]) is not str or rutype[2] != 'float32':
            raise CollectionError("Uniform type cannot de reduced to float32 only")
        else:
            count = rutype[1]
            size = count//4
            if count % 4:
                size += 1
                utype.append(('unnused', 'f4', size*4-count))
            count = size*4
            self.utype = utype
        self._vbuffer = VertexBuffer(vtype)
        self._ubuffer = DynamicBuffer( utype )
        self._ubuffer_id = 0
        self._ubuffer_shape = [0,count]

        self._dirty = True

    # ---------------------------------
    def __len__(self):
        return len(self._vbuffer)


    # ---------------------------------
    def __getitem__(self, key):
        V = self._vbuffer.vertices[key]
        I = self._vbuffer.indices[key]
        U = self._ubuffer[key]
        return Item(self, key, V, I, U)


    # ---------------------------------
    def __delitem__(self, key):
        start,end = self._vbuffer.vertices.range(key)
        del self._vbuffer[key]
        del self._ubuffer[key]
        self._vbuffer.vertices.data['a_index'][start:] -= 1
        self._vbuffer._dirty = True
        self._dirty = True


    # ---------------------------------
    def get_vertices(self):
        return self._vbuffer.vertices
    vertices = property(get_vertices)


    # ---------------------------------
    def get_indices(self):
        return self._vbuffer.indices
    indices = property(get_indices)


    # ---------------------------------
    def get_uniforms(self):
        return self._ubuffer
    uniforms = property(get_uniforms)


    # ---------------------------------
    def __getattr__(self, name):
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self,'_ubuffer')
            if name in buffer.dtype.names:
                return buffer.data[name]
        return object.__getattribute__(self,name)


    # ---------------------------------
    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self,'_ubuffer')
            if name in buffer.dtype.names:
                buffer.data[name] = value
                # buffer._dirty = True
                object.__setattr__(self, '_dirty', True)
        object.__setattr__(self, name, value)


    # ---------------------------------
    def clear(self):
        self._vbuffer.clear()
        self._ubuffer.clear()
        self._dirty = True


    # ---------------------------------
    def append(self, vertices, indices, uniforms):
        vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype)
        indices  = np.array(indices).astype(self._vbuffer.indices.dtype)
        uniforms = np.array(uniforms).astype(self._ubuffer.dtype)
        vertices['a_index'] = len(self)
        self._vbuffer.append( vertices, indices)
        self._ubuffer.append( uniforms )
        self._ubuffer_shape[0] = len(self)
        self._dirty = True


    # ---------------------------------
    def upload(self):

        if not self._dirty:
            return

        self._vbuffer.upload()

        gl.glActiveTexture( gl.GL_TEXTURE0 )
        data = self._ubuffer.data.view(np.float32)
        shape = self._ubuffer_shape
        if not self._ubuffer_id:
            self._ubuffer_id = gl.glGenTextures(1)

            gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
            gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 )
            gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE )
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0)
            gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F,
                             shape[1]//4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data )

        gl.glActiveTexture( gl.GL_TEXTURE0 )
        gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
        gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F,
                         shape[1]//4, shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data )
        #gl.glTexSubImage2D( gl.GL_TEXTURE_2D,0, 0, 0, shape[1]//4, shape[0],
        #                    gl.GL_RGBA, gl.GL_FLOAT, data);
        self._dirty = False


    # ---------------------------------
    def bake(self, vertices):
        raise NotImplemented


    # ---------------------------------
    def draw(self):
        if self._dirty:
            self.upload()

        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glEnable(gl.GL_BLEND)
        _,_,width,height = gl.glGetIntegerv( gl.GL_VIEWPORT )
        P = orthographic( 0, width, 0, height, -1, +1 )
        V = np.eye(4).astype( np.float32 )
        M = np.eye(4).astype( np.float32 )

        shader = self.shader
        shader.bind()
        gl.glActiveTexture( gl.GL_TEXTURE0 )
        shader.uniformi( 'u_uniforms', 0 )
        gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
        if self.dash_atlas:
            gl.glActiveTexture( gl.GL_TEXTURE1 )
            shader.uniformi('u_dash_atlas', 1)
            gl.glBindTexture( gl.GL_TEXTURE_2D, self.dash_atlas.texture_id )
        shader.uniform_matrixf( 'u_M', M )
        shader.uniform_matrixf( 'u_V', V )
        shader.uniform_matrixf( 'u_P', P )
        shape = self._ubuffer_shape
        shader.uniformf( 'u_uniforms_shape', shape[1]//4, shape[0])
        self._vbuffer.draw( )
        shader.unbind()
예제 #4
0
class Label(object):
    '''
    '''
    def __init__(self,
                 text,
                 family='Sans',
                 size=16,
                 bold=False,
                 italic=False,
                 color=(1.0, 1.0, 1.0, 1.0),
                 x=0,
                 y=0,
                 z=0,
                 anchor_x='left',
                 anchor_y='baseline',
                 filename='./Arial.ttf'):
        self._text = text
        self._font = get_font(filename, size)
        self._color = color
        self._x = x
        self._y = y
        self._z = z
        self._anchor_x = anchor_x
        self._anchor_y = anchor_y
        self.build()

    def build(self):
        self.vertices = np.zeros(len(self._text) * 4,
                                 dtype=[('position', 'f4', 3),
                                        ('tex_coord', 'f4', 2),
                                        ('color', 'f4', 4)])
        self.indices = np.zeros((len(self._text) * 6, ), dtype=np.uint32)

        prev = None
        x, y = 0, 0
        for i, charcode in enumerate(self._text):
            glyph = self._font[charcode]
            kerning = glyph.get_kerning(prev) / 64.0
            x0 = int(x + glyph.offset[0] + kerning)
            y0 = int(y + glyph.offset[1])
            x1 = x0 + glyph.size[0]
            y1 = y0 - glyph.size[1]
            u0 = glyph.texcoords[0]
            v0 = glyph.texcoords[1]
            u1 = glyph.texcoords[2]
            v1 = glyph.texcoords[3]
            index = i * 4
            indices = [
                index, index + 1, index + 2, index, index + 2, index + 3
            ]
            vertices = [[x0, y0, 0], [x0, y1, 0], [x1, y1, 0], [x1, y0, 0]]
            texcoords = [[u0, v0], [u0, v1], [u1, v1], [u1, v0]]
            colors = [
                self._color,
            ] * 4
            self.indices[i * 6:i * 6 + 6] = indices
            self.vertices['position'][i * 4:i * 4 + 4] = vertices
            self.vertices['tex_coord'][i * 4:i * 4 + 4] = texcoords
            self.vertices['color'][i * 4:i * 4 + 4] = colors
            x += glyph.advance[0] / 64.0 + kerning
            y += glyph.advance[1] / 64.0
            prev = charcode
        width = x + glyph.advance[0] / 64.0 + glyph.size[0]

        if self._anchor_y == 'top':
            dy = -round(self._font.ascender)
        elif self._anchor_y == 'center':
            dy = +round(-self._font.height / 2 - self._font.descender)
        elif self._anchor_y == 'bottom':
            dy = -round(self._font.descender)
        else:
            dy = 0
        if self._anchor_x == 'right':
            dx = -width / 1.0
        elif self._anchor_x == 'center':
            dx = -width / 2.0
        else:
            dx = 0
        self.vertices['position'] += self._x + round(dx), self._y + round(
            dy), self._z
        self.buffer = VertexBuffer(self.vertices, self.indices)

    def draw(self):
        gl.glDisable(gl.GL_TEXTURE_1D)
        gl.glEnable(gl.GL_TEXTURE_2D)
        gl.glDisable(gl.GL_DEPTH_TEST)
        gl.glBindTexture(gl.GL_TEXTURE_2D, self._font.texid)
        gl.glEnable(gl.GL_BLEND)
        gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
        gl.glColor(1, 1, 1, 1)
        self.buffer.draw(gl.GL_TRIANGLES)

    def _get_position(self):
        return self._x, self.y, self._z

    def _set_position(self, position):
        x, y = position
        self.vertices['position'] -= self._x, self._y, 0
        self._x, self._y = x, y
        self.vertices['position'] += x, y, 0
        self.vbo.upload()

    position = property(_get_position, _set_position)
예제 #5
0
파일: label.py 프로젝트: davidcox/glumpy
class Label(object):
    '''
    '''
    def __init__( self, text, family='Sans', size=16, bold=False, italic=False,
                  color=(1.0, 1.0, 1.0, 1.0), x=0, y=0, z=0,
                  anchor_x='left', anchor_y='baseline', filename='./Arial.ttf'):
        self._text = text
        self._font = get_font(filename, size)
        self._color = color
        self._x = x
        self._y = y
        self._z = z
        self._anchor_x = anchor_x
        self._anchor_y = anchor_y
        self.build()



    def build(self):
        self.vertices = np.zeros( len(self._text)*4,
                                  dtype = [('position',  'f4',3),
                                           ('tex_coord', 'f4',2),
                                           ('color',     'f4',4)] )
        self.indices  = np.zeros( (len(self._text)*6, ), dtype=np.uint32 )

        prev = None
        x,y = 0, 0
        for i,charcode in enumerate(self._text):
            glyph = self._font[charcode]
            kerning = glyph.get_kerning(prev)/64.0
            x0 = int(x + glyph.offset[0] + kerning)
            y0 = int(y + glyph.offset[1])
            x1 = x0 + glyph.size[0]
            y1 = y0 - glyph.size[1]
            u0 = glyph.texcoords[0]
            v0 = glyph.texcoords[1]
            u1 = glyph.texcoords[2]
            v1 = glyph.texcoords[3]
            index     = i*4
            indices   = [index, index+1, index+2, index, index+2, index+3]
            vertices  = [[x0,y0,0],[x0,y1,0],[x1,y1,0], [x1,y0,0]]
            texcoords = [[u0,v0],[u0,v1],[u1,v1], [u1,v0]]
            colors    = [self._color,]*4
            self.indices[i*6:i*6+6] = indices
            self.vertices['position'][i*4:i*4+4] = vertices
            self.vertices['tex_coord'][i*4:i*4+4] = texcoords
            self.vertices['color'][i*4:i*4+4] = colors
            x += glyph.advance[0]/64.0 + kerning
            y += glyph.advance[1]/64.0
            prev = charcode
        width = x+glyph.advance[0]/64.0+glyph.size[0]

        if self._anchor_y == 'top':
            dy = -round(self._font.ascender)
        elif self._anchor_y == 'center':
            dy = +round(-self._font.height/2-self._font.descender)
        elif self._anchor_y == 'bottom':
            dy = -round(self._font.descender)
        else:
            dy = 0
        if self._anchor_x == 'right':
            dx = -width/1.0
        elif self._anchor_x == 'center':
            dx = -width/2.0
        else:
            dx = 0
        self.vertices['position'] += self._x+round(dx), self._y+round(dy), self._z
        self.buffer = VertexBuffer(self.vertices, self.indices)


    def draw(self):
        gl.glDisable (gl.GL_TEXTURE_1D)
        gl.glEnable( gl.GL_TEXTURE_2D )
        gl.glDisable( gl.GL_DEPTH_TEST )
        gl.glBindTexture( gl.GL_TEXTURE_2D, self._font.texid )
        gl.glEnable( gl.GL_BLEND )
        gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA )
        gl.glColor(1,1,1,1)
        self.buffer.draw(gl.GL_TRIANGLES)


    def _get_position(self):
        return self._x, self.y, self._z
    def _set_position(self, position):
        x,y = position
        self.vertices['position'] -= self._x, self._y, 0
        self._x, self._y = x,y
        self.vertices['position'] += x, y, 0
        self.vbo.upload()
    position = property(_get_position, _set_position)
예제 #6
0
class Collection(object):

    # ---------------------------------
    def __init__(self, vtype, utype):
        # Convert types to lists (in case they were already dtypes) such that
        # we can append new fields
        vtype = eval(str(np.dtype(vtype)))
        utype = eval(str(np.dtype(utype)))

        # We add a uniform index to access uniform data from texture
        vtype.append( ('a_index', 'f4') )

        # Check if given utype is made of float32 only
        rutype = dtype_reduce(utype)
        if type(rutype[0]) is not str or rutype[2] != 'float32':
            raise CollectionError("Uniform type cannot de reduced to float32 only")
        else:
            count = rutype[1]
            count2 = int(math.pow(2, math.ceil(math.log(count, 2))))
            if (count2 - count) > 0:
                utype.append(('unused', 'f4', count2-count))
            self._count = count2
            self.utype = utype
        
        self._vbuffer = VertexBuffer(vtype)
        self._ubuffer = DynamicBuffer( utype )
        self._ubuffer_id = 0
        self._max_texture_size = gl.glGetInteger(gl.GL_MAX_TEXTURE_SIZE)
        self._compute_ushape(1)
        self._ubuffer.reserve( self._ushape[1] / (count/4) )
        self._dirty = True


    # ---------------------------------
    def _compute_ushape(self, size=1):
        max_texsize = self._max_texture_size
        cols = max_texsize//(self._count/4)
        rows = (size // cols)+1
        self._ushape = rows, cols*(self._count/4), self._count


    # ---------------------------------
    def __len__(self):
        return len(self._vbuffer)


    # ---------------------------------
    def __getitem__(self, key):
        V = self._vbuffer.vertices[key]
        I = self._vbuffer.indices[key]
        U = self._ubuffer[key]
        return Item(self, key, V, I, U)


    # ---------------------------------
    def __delitem__(self, key):
        start,end = self._vbuffer.vertices.range(key)
        del self._vbuffer[key]
        del self._ubuffer[key]
        self._vbuffer.vertices.data['a_index'][start:] -= 1
        self._vbuffer._dirty = True
        self._dirty = True



    # ---------------------------------
    def get_vbuffer(self):
        return self._vbuffer
    vbuffer = property(get_vbuffer)

    # ---------------------------------
    def get_vertices(self):
        return self._vbuffer.vertices
    vertices = property(get_vertices)


    # ---------------------------------
    def get_indices(self):
        return self._vbuffer.indices
    indices = property(get_indices)


    # ---------------------------------
    def get_uniforms(self):
        return self._ubuffer
    uniforms = property(get_uniforms)


    # ---------------------------------
    def get_attributes(self):
        return self._vbuffer._attributes
    attributes = property(get_attributes)


    # ---------------------------------
    def __getattr__(self, name):
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self,'_ubuffer')
            if name in buffer.dtype.names:
                return buffer.data[name]
        return object.__getattribute__(self,name)


    # ---------------------------------
    def __setattr__(self, name, value):
        object.__setattr__(self, name, value)
        if hasattr(self, '_ubuffer'):
            buffer = object.__getattribute__(self,'_ubuffer')
            if name in buffer.dtype.names:
                buffer.data[name] = value
                # buffer._dirty = True
                object.__setattr__(self, '_dirty', True)
        object.__setattr__(self, name, value)


    # ---------------------------------
    def clear(self):
        self._vbuffer.clear()
        self._ubuffer.clear()
        self._dirty = True


    # ---------------------------------
    def append(self, vertices, indices, uniforms, splits=None):
        vertices = np.array(vertices).astype(self._vbuffer.vertices.dtype)
        indices  = np.array(indices).astype(self._vbuffer.indices.dtype)
        uniforms = np.array(uniforms).astype(self._ubuffer.dtype)

        if splits is None:
            vertices['a_index'] = len(self)
            self._vbuffer.append( vertices, indices )
            self._ubuffer.append( uniforms )
            self._compute_ushape(len(self))
        elif len(splits) == 2:
            vsize,isize = splits[0], splits[1]
            if (vertices.size % vsize) != 0:
                raise( RuntimeError,
                       "Cannot split vertices data into %d pieces" % vsize)
            if (indices.size % isize) != 0:
                raise( RuntimeError,
                       "Cannot split indices data into %d pieces" % vsize)
            vcount = vertices.size//vsize
            icount = indices.size//isize
            ucount = uniforms.size
            n = ucount
            if vcount != icount or vcount != ucount:
                raise( RuntimeError,
                       "Vertices/indices/uniforms cannot be split")
            vertices['a_index'] = len(self)+np.repeat(np.arange(n),vsize)
            self._vbuffer.append( vertices, indices, (vsize,isize))
            self._ubuffer.append( uniforms )
            self._compute_ushape(len(self))
        else:
            raise(RuntimeError, "Splits argument not understood")
        self._dirty = True


    # ---------------------------------
    def upload(self):

        if not self._dirty:
            return
        self._vbuffer.upload()
        self.upload_uniforms()
        self._dirty = False


    # ---------------------------------
    def upload_uniforms(self):

        gl.glActiveTexture( gl.GL_TEXTURE0 )
        data = self._ubuffer.data.view(np.float32)
        shape = self._ushape

        if not self._ubuffer_id:
            self._ubuffer_id = gl.glGenTextures(1)

            gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
            gl.glPixelStorei( gl.GL_UNPACK_ALIGNMENT, 1 )
            gl.glPixelStorei( gl.GL_PACK_ALIGNMENT, 1 )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE )
            gl.glTexParameterf( gl.GL_TEXTURE_2D,
                                gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE )
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_BASE_LEVEL, 0)
            gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAX_LEVEL, 0)
            gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F,
                             shape[1], shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data )
        gl.glActiveTexture( gl.GL_TEXTURE0 )
        gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
        gl.glTexImage2D( gl.GL_TEXTURE_2D, 0, gl.GL_RGBA32F,
                         shape[1], shape[0], 0, gl.GL_RGBA, gl.GL_FLOAT, data )


    # ---------------------------------
    def draw(self, mode=gl.GL_TRIANGLES, uniforms = {}):
        if self._dirty:
            self.upload()
        shader = self.shader
        shader.bind()
        gl.glActiveTexture( gl.GL_TEXTURE0 )
        shader.uniformi( 'u_uniforms', 0 )
        gl.glBindTexture( gl.GL_TEXTURE_2D, self._ubuffer_id )
        for name,value in uniforms.items():
            shader.uniform(name, value)
        shader.uniformf('u_uniforms_shape', *self._ushape)
        self._vbuffer.draw(mode)
        shader.unbind()