예제 #1
0
    def __init__(self, font, camera, max_chars=100, point_size=48):
        """ Arguments:
    *font*:
      A PointFont object.
    *camera*:
      camera to use for drawing the text.  Normally a fixed 2d camera.
    *max_chars*:
      maximum number of chars, which determines the number of points in the buffer
    *point_size*:
      size of "default" characters created using the Points class and the
      font. This is further scaled by the TextBlock.size
      This refinement is needed to allow pointsize to be different in Points from
      Font to avoid clipping or overlap of corners when rotation some truetype fonts
    """
        self.max_chars = max_chars
        self.font = font
        self.shader = Shader.create("uv_pointsprite")

        self.locations = np.zeros((max_chars, 3))
        # :,2 for size and z offset.
        # size=fract(location[2] range 0.0 to 0.999)
        # zoffset = (location[2] - size)*0.1

        self.normals = np.zeros((max_chars, 3))
        # :,0 for rotation
        # :,1 for red and green, red=normal[1]/999, green=fract(normal[1])
        # :,2 for blue and alpha, blue=normal[2]/999, alpha=fract(normal[2])
        self.normals[:, 1] = 0.0
        self.normals[:, 2] = 0.0
        self.uv = np.zeros((max_chars, 2))  # u picnum.u v

        self.text_blocks = []
        self._first_free_char = 0
        self._do_buffer_reinit = False

        self.point_size = point_size
        self.text = Points(camera=camera,
                           vertices=self.locations,
                           normals=self.normals,
                           tex_coords=self.uv,
                           point_size=self.point_size)
        self.text.set_draw_details(self.shader, [self.font])
        self.text.unif[
            48] = 0.928 / self.font.grid_size  # used to hold "patch size" passed to shader - margin to allow rotating
        #Reset all characters to space so there are no false character shadows
        try:
            glyph = self.font.glyph_table[
                ' ']  #u' ' doesn't work on python3.2!!
        except:
            glyph = list(
                self.font.glyph_table.values())[0]  #in case ' ' isn't there
        self.uv[:] = glyph[0:2]
예제 #2
0
    def __init__(self,
                 shader="post_base",
                 mipmap=False,
                 add_tex=None,
                 scale=1.0,
                 camera=None,
                 divide=1):
        """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer. Keyword Arguments:

      *shader*
        to use when drawing sprite, defaults to post_base, a simple
        3x3 convolution that does basic edge detection. Can be copied to
        project directory and modified as required.

      *mipmap*
        can be set to True with slight cost to speed, or use fxaa shader

      *add_tex*
        list of textures. If additional textures can be used by the shader
        then they can be added here.
        
      *scale*
        will only render this proportion of the full screen which will
        then be mapped to the full uv of the Sprite. The camera object
        passed (below) will need to have the same scale set to avoid
        perspective distortion
        
      *camera*
        the camera to use for rendering to the offscreen texture
        
      *divide*
        allow the sprite to be created with intermediate vertices to allow
        interesting vertex shader effects
     
    """
        super(PostProcess, self).__init__("postprocess")
        self.scale = scale
        # load shader
        if type(shader) == Shader:
            self.shader = shader
        else:
            self.shader = Shader.create(shader)
        if camera is None:
            self.viewcam = Camera.instance(
            )  # in case this is prior to one being created
        else:
            self.viewcam = camera
        self.camera = Camera(is_3d=False)
        self.sprite = LodSprite(camera=self.camera,
                                z=20.0,
                                w=self.ix,
                                h=self.iy,
                                n=divide)
        self.sprite.set_2d_size(w=self.ix, h=self.iy)
        self.tex_list = [
            self.color, self.depth
        ]  # TODO check if this self reference causes graphics memory leaks
        if add_tex:
            self.tex_list.extend(add_tex)
        self.sprite.set_draw_details(self.shader, self.tex_list, 0.0, 0.0)
        for b in self.sprite.buf:
            b.unib[6] = self.scale  # ufact
            b.unib[7] = self.scale  # vfact
            b.unib[9] = (1.0 - self.scale) * 0.5  # uoffset
            b.unib[10] = (1.0 - self.scale) * 0.5  # voffset
        self.blend = True
        self.mipmap = mipmap
예제 #3
0
    def __init__(self,
                 pex_file,
                 emission_rate=10,
                 scale=1.0,
                 rot_rate=None,
                 rot_var=0.0,
                 new_batch=0.1,
                 hardness=2.0,
                 **kwargs):
        ''' has to be supplied with a pex xml type file to parse. The results
    are loaded into new attributes of the instance of this class with identifiers
    matching the Elements of the pex file. There is zero checking for the
    correct file format.

      pex_file:       file name. if "circle" then lite option doesn't
                      use texture lookup and used mat_pointsprite shader
      emission_rate:  new particles per second
      scale:          scale the point size and location
      rot_rate:       UV mapping rotates
      rot_var:        variance in rotation rate
      new_batch:      proportion of emission_rate to batch (for efficiency)
      hardness:       for lite version

    The following attributes are created from the pex file and can be subsequently
    altered. i.e. self.sourcePosition['x'] += 2.0

      self.texture={name:'particle.png'}
      self.sourcePosition={x:160.00,y:369.01}
      self.sourcePositionVariance={x:60.00,y:0.00}
      self.speed=138.16
      self.speedVariance=0.00
      self.particleLifeSpan=0.7000
      self.particleLifespanVariance=0.0000
      self.angle=224.38
      self.angleVariance=360.00
      self.gravity={x:0.00,y:-1400.00}
      self.radialAcceleration=0.00
      self.tangentialAcceleration=0.00
      self.radialAccelVariance=0.00
      self.tangentialAccelVariance=-0.00
      self.startColor={red:0.15,green:0.06,blue:1.00,alpha:1.00}
      self.startColorVariance={red:0.00,green:0.00,blue:0.00,alpha:0.00}
      self.finishColor={red:0.00,green:0.14,blue:0.23,alpha:0.00}
      self.finishColorVariance={red:0.00,green:0.00,blue:0.00,alpha:0.00}
      self.maxParticles=300
      self.startParticleSize=43.79
      self.startParticleSizeVariance=0.00
      self.finishParticleSize=138.11
      self.FinishParticleSizeVariance=0.00
      self.duration=-1.00
      self.emitterType=0
      self.maxRadius=100.00
      self.maxRadiusVariance=0.00
      self.minRadius=0.00
      self.rotatePerSecond=0.00
      self.rotatePerSecondVariance=0.00
      self.blendFuncSource=770
      self.blendFuncDestination=772
      self.rotationStart=0.00
      self.rotationStartVariance=0.00
      self.rotationEnd=0.00
      self.rotationEndVariance=0.00
    '''
        # first parse the pex file, json would have been nicer than xml!
        _config = parse(pex_file).childNodes[0].childNodes
        for c in _config:
            if c.localName is not None:
                key = c.localName
                val = {}
                for v in c.attributes.items():
                    try:
                        v_tp = int(v[1])  # try int first
                    except ValueError:
                        try:
                            v_tp = float(v[1])  # if not try float
                        except ValueError:
                            v_tp = v[1]  # otherwise leave as string
                    if v[0] == 'value':  # single value 'value' don't use dictionary
                        val = v_tp
                        break
                    else:
                        val[v[0]] = v_tp  # not just a value
                self.__setattr__(key, val)

        self._emission_rate = emission_rate  # particles per second
        self._last_emission_time = None
        self._last_time = None
        self._new_batch = emission_rate * new_batch  # to clump new particles
        self.scale = scale
        self.rot_rate = rot_rate
        self.rot_var = rot_var
        # make a flag to avoid this expensive operation if no accelerators
        self.any_acceleration = (self.gravity['x'] != 0.0
                                 or self.gravity['y'] != 0.0
                                 or self.radialAcceleration != 0.0
                                 or self.tangentialAcceleration != 0.0)
        self.any_colorchange = any(self.startColor[i] != self.finishColor[i]
                                   for i in ('red', 'green', 'blue', 'alpha'))
        ''' Buffer.array_buffer holds
    [0] vertices[0] x position of centre of point relative to centre of screen in pixels
    [1] vertices[1] y position
    [2] vertices[2] z depth but fract(z) is used as a multiplier for point size
    [3] normals[0]  rotation in radians
    [4] normals[1]  red and green values to multiply with the texture
    [5] normals[2]  blue and alph values to multiply with the texture. The values
                    are packed into the whole number and fractional parts of
                    the float i.e. where R and G are between 0.0 and 0.999
                    normals[:,2] = floor(999 * R) + G
    [6] tex_coords[0] distance of left side of sprite square from left side of
                    texture in uv scale 0.0 to 1.0
    [7] tex_coords[1] distance of top of sprite square from top of texture
       for lite version using the mat_pointsprite shader
    [3:7] hold RGBA in simple float form

       make additional numpy array to hold the particle info
    arr[0]          x velocity
    arr[1]          y velocity
    arr[2]          lifespan
    arr[3]          lifespan remaining
    arr[4:8]        rgba target values
    arr[8:12]       rgba difference
    arr[12]         size delta (finish size - start size) / full_lifespan
    arr[13]         radial acceleration
    arr[14]         tangential acceleration
    '''
        self.arr = np.zeros((self.maxParticles, 15), dtype='float32')
        self.point_size = max(self.startParticleSize +
                              self.startParticleSizeVariance,
                              self.finishParticleSize +
                              self.FinishParticleSizeVariance)  #NB capital F!
        super(PexParticles,
              self).__init__(vertices=np.zeros((self.maxParticles, 3),
                                               dtype='float32'),
                             normals=np.zeros((self.maxParticles, 3),
                                              dtype='float32'),
                             tex_coords=np.zeros((self.maxParticles, 2),
                                                 dtype='float32'),
                             point_size=self.point_size * self.scale,
                             **kwargs)  # pass to Points.__init__()
        if self.texture['name'] == 'circle':  # TODO alternative geometries
            self.lite = True
            shader = Shader.create('mat_pointsprite')
            self.set_shader(shader)
            self.buf[0].unib[0] = hardness
        else:
            self.lite = False
            shader = Shader.create('uv_pointsprite')
            try:
                tex = Texture(self.texture['name'])  # obvious first!
            except:
                import os
                tex = Texture(
                    os.path.join(
                        os.path.split(pex_file)[0], self.texture['name']))
            self.set_draw_details(shader, [tex])
            self.unif[48] = 1.0  # sprite uses whole image
예제 #4
0
  def __init__(self, shader="uv_flat", mipmap=False, separation=0.4, interlace=0):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer. Keyword Arguments:

      *shader*
        to use when drawing sprite, defaults to uv_flat.

      *mipmap*
        can be set to True with slight cost to speed, or use fxaa shader

      *separation*
        distance between the two camera positions - how wide apart the
        eye views are.

      *interlace*
        if interlace > 0 then the images are not taken with glScissor and
        must be drawn with a special interlacing shader.
    """
    # load shader
    if interlace <= 0: # i.e. default side by side behaviour
      self.shader = Shader.create(shader)
    else:
      self.shader = Shader(vshader_source = """
precision mediump float;
attribute vec3 vertex;
attribute vec2 texcoord;
uniform mat4 modelviewmatrix[2];
varying vec2 texcoordout;
void main(void) {
  texcoordout = texcoord;
  gl_Position = modelviewmatrix[1] * vec4(vertex,1.0);
}
    """, fshader_source = """
precision mediump float;
uniform sampler2D tex0;
uniform sampler2D tex1;
varying vec2 texcoordout;
void main(void) {{
  vec4 texc0 = texture2D(tex0, texcoordout);
  vec4 texc1 = texture2D(tex1, texcoordout);
  vec2 coord = vec2(gl_FragCoord);
  gl_FragColor = mix(texc0, texc1, step(0.5, fract(coord.x / {:f})));
}}
    """.format(interlace * 2.0))

    self.camera_3d = Camera() # create 3d cam first so it becomes default instance
    self.forMtrx = np.identity(4, dtype='float32') # initially not rotated
    self.position = [0.0, 0.0, 0.0]
    self.camera_2d = Camera(is_3d=False)
    self.offs = separation / 2.0
    self.interlace = interlace
    self.textures = []
    self.sprites = []
    self.tex_list = []
    for i in range(2):
      self.textures.append(OffScreenTexture(name="stereo"))
      ix, iy = self.textures[i].ix, self.textures[i].iy
      #two sprites full width but moved so that they are centred on the
      #left and right edges. The offset values then move the uv mapping
      #so the image is on the right of the left sprite and left of the
      #right sprite
      self.sprites.append(Sprite(z=20.0, w=ix, h=iy, flip=True))
      if interlace <= 0:
        self.sprites[i].positionX(-ix/2.0 + i*ix)
        self.sprites[i].set_offset((i * 0.5 - 0.25, 0.0))
      else:
        self.sprites[i].set_2d_size(w=ix, h=iy)
      self.textures[i].blend = True
      self.textures[i].mipmap = mipmap
      self.tex_list.append(self.textures[i])
    opengles.glColorMask(1, 1, 1, 1)