Ejemplo n.º 1
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
        self.shader = Shader(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(z=20.0, w=self.ix, h=self.iy, n=divide)
        self.sprite.set_2d_size(w=self.ix, h=self.iy)
        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
        self.tex_list = [
            self
        ]  # TODO check if this self reference causes graphics memory leaks
        if add_tex:
            self.tex_list.extend(add_tex)
Ejemplo n.º 2
0
    def __init__(self, position, light, scale=10.0):
        """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
        super(ShadowCaster, self).__init__("shadow_caster")

        self.LIGHT_CAM = Camera(is_3d=False, scale=scale)
        l_p = light.lightpos
        l_len = (l_p[0]**2 + l_p[1]**2 + l_p[2]**2)**0.5
        self.OFFSET = [200.0 * i / l_len for i in l_p]
        self.LIGHT_CAM.position(
            [position[i] - o for i, o in enumerate(self.OFFSET)])
        self.tilt, self.rot = self.LIGHT_CAM.point_at(position)
        self.cast_shader = Shader("shadowcast")
Ejemplo n.º 3
0
 def __init__(self, emap, light):
   """ calls Texture.__init__ but doesn't need to set file name as
   texture generated from the framebuffer
   """
   super(ShadowCaster, self).__init__("shadow_caster")
   # load shader for casting shadows and camera
   self.cshader = Shader("uv_flat")
   self.mshader = Shader("mat_flat")
   # keep copy of ElevationMap
   self.emap = emap
   self.emap.set_material((0.0, 0.0, 0.0)) # hide bits below ground
   #TODO doesn't cope with  z light positions
   self.eye = [-500.0 * i for i in light.lightpos] # good distance away
   if self.eye[1] <= 0: # must have +ve y
     self.eye[1] = 500.0
   if abs(self.eye[0]) > abs(self.eye[2]): #x val is bigger than z val
     #change scale so map just fits on screen
     if self.eye[0] < 0:
       su, sv  = 1.0, 1.0
     else:
       su, sv  = -1.0, -1.0
     self.scaleu = float(self.iy) / self.emap.width
     self.scalev = float(self.ix)/ self.emap.depth
     self.eye[2] = 0
     self.scaleu = self.scaleu / self.eye[1] * (self.eye[0]**2 + self.eye[1]**2)**0.5
     self.emap.unif[50] = 1.0 #orientation flag
     self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / self.eye[1] #height adjustment
   else:
     #change scale so map just fits on screen
     if self.eye[2] < 0:
       su, sv  = 1.0, -1.0
     else:
       su, sv  = -1.0, 1.0
     self.scaleu = float(self.iy) / self.emap.depth
     self.scalev = float(self.ix)/ self.emap.width
     self.eye[0] = 0
     self.scaleu = self.scaleu / self.eye[1] * (self.eye[2]**2 + self.eye[1]**2)**0.5
     self.emap.unif[50] = 0.0
     self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / self.eye[1]
   if abs(self.scaleu) > abs(self.scalev):
     self.scale = 3.0 * self.scalev # multiplication factor to reduce pixeliness
   else:
     self.scale = 3.0 * self.scaleu
   self.scaleu = su * self.scale / self.scaleu # reused later in end_cast
   self.scalev = sv * self.scale / self.scalev
   self.camera0 = Camera() # default instance created as normal, just in case!
   self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
   # load shader for drawing map with shadows
   self.dshader = Shader("shadowcast")
Ejemplo n.º 4
0
  def _loop_begin(self):
    # TODO(rec):  check if the window was resized and resize it, removing
    # code from MegaStation to here.
    if not ON_PI:
      n = xlib.XEventsQueued(self.opengl.d, xlib.QueuedAfterFlush)
      for i in range(n):
        if xlib.XCheckMaskEvent(self.opengl.d, KeyPressMask, self.ev):
          self.event_list.append(self.ev)
        else:
          xlib.XNextEvent(self.opengl.d, self.ev)
          if self.ev.type == ClientMessage:
            if (self.ev.xclient.data.l[0] == self.opengl.WM_DELETE_WINDOW.value):
              self.destroy()
    self.clear()
    with self.lock:
      self.sprites_to_load, to_load = set(), self.sprites_to_load
      self.sprites.extend(to_load)
    self._for_each_sprite(lambda s: s.load_opengl(), to_load)

    if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
      from pi3d.Camera import Camera
      camera = Camera.instance()
      if camera:
        camera.was_moved = False

    if self.tidy_needed:
      self._tidy()
Ejemplo n.º 5
0
  def __init__(self, shader="post_base", mipmap=False, add_tex=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.
     
    """
    super(PostProcess, self).__init__("postprocess")
    # load shader
    self.shader = Shader(shader)
    dummycam = Camera.instance() # in case this is prior to one being created 
    self.camera = Camera(is_3d=False)
    self.sprite = LodSprite(z=20.0, w=self.ix, h=self.iy, n=divide)
    self.sprite.set_2d_size(w=self.ix, h=self.iy)
    self.alpha = False
    self.blend = True
    self.mipmap = mipmap
    self.tex_list = [self] # TODO check if this self reference causes graphics memory leaks
    if add_tex:
      self.tex_list.extend(add_tex)
Ejemplo n.º 6
0
    def _loop_begin(self):
        # TODO(rec):  check if the window was resized and resize it, removing
        # code from MegaStation to here.
        if PLATFORM == PLATFORM_WINDOWS:
            if pygame.event.get(pygame.QUIT):
                self.destroy()
        elif PLATFORM != PLATFORM_PI and PLATFORM != PLATFORM_ANDROID:
            n = xlib.XEventsQueued(self.opengl.d, xlib.QueuedAfterFlush)
            for i in range(n):
                if xlib.XCheckMaskEvent(self.opengl.d, KeyPressMask, self.ev):
                    self.event_list.append(self.ev)
                else:
                    xlib.XNextEvent(self.opengl.d, self.ev)
                    if self.ev.type == ClientMessage:
                        if (self.ev.xclient.data.l[0] ==
                                self.opengl.WM_DELETE_WINDOW.value):
                            self.destroy()
        self.clear()
        with self.lock:
            self.sprites_to_load, to_load = set(), self.sprites_to_load
            self.sprites.extend(to_load)
        self._for_each_sprite(lambda s: s.load_opengl(), to_load)

        if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
            from pi3d.Camera import Camera
            camera = Camera.instance()
            if camera is not None:
                camera.was_moved = False

        if self.tidy_needed:
            self._tidy()
Ejemplo n.º 7
0
Archivo: Display.py Proyecto: bpow/pi3d
  def _loop_begin(self):
    # TODO(rec):  check if the window was resized and resize it, removing
    # code from MegaStation to here.
    if pi3d.USE_PYGAME:
      import pygame # although done in __init__ ...python namespaces aarg!!!
      if pygame.event.get(pygame.QUIT):
        self.destroy()
    elif pi3d.PLATFORM != pi3d.PLATFORM_PI and pi3d.PLATFORM != pi3d.PLATFORM_ANDROID:
      n = xlib.XEventsQueued(self.opengl.d, xlib.QueuedAfterFlush)
      for i in range(n):
        if xlib.XCheckMaskEvent(self.opengl.d, KeyPressMask, self.ev):
          self.event_list.append(self.ev)
        else:
          xlib.XNextEvent(self.opengl.d, self.ev)
          if self.ev.type == ClientMessage:
            if (self.ev.xclient.data.l[0] == self.opengl.WM_DELETE_WINDOW.value):
              self.destroy()
    self.clear()
    with self.lock:
      self.sprites_to_load, to_load = set(), self.sprites_to_load
      self.sprites.extend(to_load)
    self._for_each_sprite(lambda s: s.load_opengl(), to_load)

    if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
      from pi3d.Camera import Camera
      camera = Camera.instance()
      if camera is not None:
        camera.was_moved = False

    if self.tidy_needed:
      self._tidy()
Ejemplo n.º 8
0
    def _loop_begin(self):
        # TODO(rec):  check if the window was resized and resize it, removing
        # code from MegaStation to here.
        if pi3d.USE_PYGAME:
            import pygame  # although done in __init__ ...python namespaces aarg!!!
            if pygame.event.get(pygame.QUIT):
                self.destroy()
        elif PLATFORM != PLATFORM_PI and PLATFORM != PLATFORM_ANDROID:
            n = xlib.XEventsQueued(self.opengl.d, xlib.QueuedAfterFlush)
            for _ in range(n):
                xlib.XNextEvent(self.opengl.d, self.ev)
                if self.ev.type == KeyPress or self.ev.type == KeyRelease:
                    self.event_list.append(self.ev)
                elif self.ev.type == ClientMessage:
                    if (self.ev.xclient.data.l[0] ==
                            self.opengl.WM_DELETE_WINDOW.value):
                        self.destroy()
        self.clear()
        with self.lock:
            self.sprites_to_load, to_load = set(), self.sprites_to_load
            self.sprites.extend(to_load)
        self._for_each_sprite(lambda s: s.load_opengl(), to_load)

        if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
            from pi3d.Camera import Camera
            #camera = Camera.instance()
            #if camera is not None:
            #  camera.was_moved = False
            cameras = Camera.all_instances()
            if cameras is not None:
                for camera in cameras:
                    camera.was_moved = False

        if self.tidy_needed:
            self._tidy()
Ejemplo n.º 9
0
  def draw(self, shader=None, txtrs=None, ntl=None, shny=None, camera=None, mlist=[], light_camera=None):
    """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
    self.load_opengl() # really just to set the flag so _unload_opengl runs

    camera = camera or self._camera or Camera.instance()
    
    if not camera.mtrx_made:
      camera.make_mtrx()
    if light_camera and not light_camera.mtrx_made:
      light_camera.make_mtrx()

    if self.MFlg or len(mlist) > 0 or len(self.children) > 0:
      # Calculate rotation and translation matrix for this model using numpy.
      self.MRaw = self.tr1
      if self.rozflg:
        self.MRaw = np.dot(self.roz, self.MRaw)
      if self.roxflg:
        self.MRaw = np.dot(self.rox, self.MRaw)
      if self.royflg:
        self.MRaw = np.dot(self.roy, self.MRaw)
      if self.sclflg:
        self.MRaw = np.dot(self.scl, self.MRaw)
      if self.tr2flg:
        self.MRaw = np.dot(self.tr2, self.MRaw)

      # child drawing addition #############
      newmlist = [m for m in mlist]
      newmlist.append(self.MRaw)
      if len(self.children) > 0:
        for c in self.children:
          c.draw(shader, txtrs, ntl, shny, camera, newmlist, light_camera) # TODO issues where child doesn't use same shader 
      for m in mlist[-1::-1]:
        self.MRaw = np.dot(self.MRaw, m)
      ######################################
      self.M[0,:,:] = self.MRaw[:,:]
      #self.M[0:16] = c_floats(self.MRaw.reshape(-1).tolist()) #pypy version
      self.M[1,:,:] = np.dot(self.MRaw, camera.mtrx)[:,:]
      #self.M[16:32] = c_floats(np.dot(self.MRaw, camera.mtrx).reshape(-1).tolist()) #pypy
      if light_camera is not None:
        self.M[2,:,:] = np.dot(self.MRaw, light_camera.mtrx)[:,:]
      self.MFlg = False

    elif camera.was_moved:
      # Only do this if it's not done because model moved.
      self.M[1,:,:] = np.dot(self.MRaw, camera.mtrx)[:,:]
      if light_camera is not None:
        self.M[2,:,:] = np.dot(self.MRaw, light_camera.mtrx)[:,:]

    if camera.was_moved:
      self.unif[18:21] = camera.eye[0:3]

    for b in self.buf:
      # Shape.draw has to be passed either parameter == None or values to pass
      # on.
      b.draw(self, self.M, self.unif, shader, txtrs, ntl, shny)
Ejemplo n.º 10
0
Archivo: Shape.py Proyecto: aolyf/pi3d
  def draw(self, shader=None, txtrs=None, ntl=None, shny=None, camera=None, mlist=[], light_camera=None):
    """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
    self.load_opengl() # really just to set the flag so _unload_opengl runs

    camera = camera or self._camera or Camera.instance()
    
    if not camera.mtrx_made:
      camera.make_mtrx()
    if light_camera and not light_camera.mtrx_made:
      light_camera.make_mtrx()

    if self.MFlg or len(mlist) > 0 or len(self.children) > 0:
      # Calculate rotation and translation matrix for this model using numpy.
      self.MRaw = self.tr1
      if self.rozflg:
        self.MRaw = dot(self.roz, self.MRaw)
      if self.roxflg:
        self.MRaw = dot(self.rox, self.MRaw)
      if self.royflg:
        self.MRaw = dot(self.roy, self.MRaw)
      if self.sclflg:
        self.MRaw = dot(self.scl, self.MRaw)
      if self.tr2flg:
        self.MRaw = dot(self.tr2, self.MRaw)

      # child drawing addition #############
      newmlist = [m for m in mlist]
      newmlist.append(self.MRaw)
      if len(self.children) > 0:
        for c in self.children:
          c.draw(shader, txtrs, ntl, shny, camera, newmlist, light_camera) # TODO issues where child doesn't use same shader 
      for m in mlist[-1::-1]:
        self.MRaw = dot(self.MRaw, m)
      ######################################
      self.M[0,:,:] = self.MRaw[:,:]
      #self.M[0:16] = c_floats(self.MRaw.reshape(-1).tolist()) #pypy version
      self.M[1,:,:] = dot(self.MRaw, camera.mtrx)[:,:]
      #self.M[16:32] = c_floats(dot(self.MRaw, camera.mtrx).reshape(-1).tolist()) #pypy
      if light_camera is not None:
        self.M[2,:,:] = dot(self.MRaw, light_camera.mtrx)[:,:]
      self.MFlg = False

    elif camera.was_moved:
      # Only do this if it's not done because model moved.
      self.M[1,:,:] = dot(self.MRaw, camera.mtrx)[:,:]
      if light_camera is not None:
        self.M[2,:,:] = dot(self.MRaw, light_camera.mtrx)[:,:]

    if camera.was_moved:
      self.unif[18:21] = camera.eye[0:3]

    for b in self.buf:
      # Shape.draw has to be passed either parameter == None or values to pass
      # on.
      b.draw(self, self.M, self.unif, shader, txtrs, ntl, shny)
Ejemplo n.º 11
0
    def draw(self,
             shader=None,
             txtrs=None,
             ntl=None,
             shny=None,
             camera=None,
             mlist=[]):
        """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
        self.load_opengl(
        )  # really just to set the flag so _unload_opengl runs

        from pi3d.Camera import Camera

        camera = camera or self._camera or Camera.instance()
        shader = shader or self.shader
        shader.use()

        if self.MFlg == True or len(mlist):
            # Calculate rotation and translation matrix for this model using numpy.
            self.MRaw = dot(
                self.tr2,
                dot(self.scl,
                    dot(self.roy, dot(self.rox, dot(self.roz, self.tr1)))))
            # child drawing addition #############
            newmlist = [m for m in mlist]
            newmlist.append(self.MRaw)
            if len(self.children) > 0:
                for c in self.children:
                    c.draw(shader, txtrs, ntl, shny, camera, newmlist)
            for m in mlist[-1::-1]:
                self.MRaw = dot(self.MRaw, m)
            ######################################
            self.M[0:16] = self.MRaw.ravel()
            #self.M[0:16] = c_floats(self.MRaw.reshape(-1).tolist()) #pypy version
            self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()
            #self.M[16:32] = c_floats(dot(self.MRaw, camera.mtrx).reshape(-1).tolist()) #pypy
            self.MFlg = False

        elif camera.was_moved:
            # Only do this if it's not done because model moved.
            self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()

        if camera.was_moved:
            self.unif[18:21] = camera.eye[0:3]

        opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2,
                                    ctypes.c_int(0), ctypes.byref(self.M))

        opengles.glUniform3fv(shader.unif_unif, 20, ctypes.byref(self.unif))
        for b in self.buf:
            # Shape.draw has to be passed either parameter == None or values to pass
            # on.
            b.draw(self, shader, txtrs, ntl, shny)
Ejemplo n.º 12
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
    self.shader = Shader(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(z=20.0, w=self.ix, h=self.iy, n=divide)
    self.sprite.set_2d_size(w=self.ix, h=self.iy)
    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.alpha = False
    self.blend = True
    self.mipmap = mipmap
    self.tex_list = [self] # TODO check if this self reference causes graphics memory leaks
    if add_tex:
      self.tex_list.extend(add_tex)
Ejemplo n.º 13
0
Archivo: Shape.py Proyecto: Biniou/pi3d
  def draw(self, shader=None, txtrs=None, ntl=None, shny=None, camera=None, mlist=[]):
    """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
    self.load_opengl() # really just to set the flag so _unload_opengl runs

    from pi3d.Camera import Camera

    camera = camera or self._camera or Camera.instance()
    shader = shader or self.shader
    shader.use()

    if self.MFlg == True or len(mlist):
      # Calculate rotation and translation matrix for this model using numpy.
      self.MRaw = dot(self.tr2,
        dot(self.scl,
            dot(self.roy,
                dot(self.rox,
                    dot(self.roz, self.tr1)))))
      # child drawing addition #############
      newmlist = [m for m in mlist]
      newmlist.append(self.MRaw)
      if len(self.children) > 0:
        for c in self.children:
          c.draw(shader, txtrs, ntl, shny, camera, newmlist)
      for m in mlist[-1::-1]:
        self.MRaw = dot(self.MRaw, m)
      ######################################
      self.M[0:16] = self.MRaw.ravel()
      #self.M[0:16] = c_floats(self.MRaw.reshape(-1).tolist()) #pypy version
      self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()
      #self.M[16:32] = c_floats(dot(self.MRaw, camera.mtrx).reshape(-1).tolist()) #pypy
      self.MFlg = False

    elif camera.was_moved:
      # Only do this if it's not done because model moved.
      self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()

    if camera.was_moved:
      self.unif[18:21] = camera.eye[0:3]

    opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2,
                                ctypes.c_int(0),
                                ctypes.byref(self.M))

    opengles.glUniform3fv(shader.unif_unif, 20, ctypes.byref(self.unif))
    for b in self.buf:
      # Shape.draw has to be passed either parameter == None or values to pass
      # on.
      b.draw(self, shader, txtrs, ntl, shny)
Ejemplo n.º 14
0
  def __init__(self, position, light, scale=10.0):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
    super(ShadowCaster, self).__init__("shadow_caster")

    self.LIGHT_CAM = Camera(is_3d=False, scale=scale)
    l_p = light.lightpos
    l_len = (l_p[0]**2 + l_p[1]**2 + l_p[2]**2)**0.5
    self.OFFSET = [200.0 * i / l_len for i in l_p]
    self.LIGHT_CAM.position([position[i] - o for i, o in enumerate(self.OFFSET)])
    self.tilt, self.rot = self.LIGHT_CAM.point_at(position)
    self.cast_shader = Shader("shadowcast")
Ejemplo n.º 15
0
class ShadowCaster(OffScreenTexture):
  """For creating a depth-of-field blurring effect on selected objects"""
  def __init__(self, position, light, scale=10.0):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
    super(ShadowCaster, self).__init__("shadow_caster")

    self.LIGHT_CAM = Camera(is_3d=False, scale=scale)
    l_p = light.lightpos
    l_len = (l_p[0]**2 + l_p[1]**2 + l_p[2]**2)**0.5
    self.OFFSET = [200.0 * i / l_len for i in l_p]
    self.LIGHT_CAM.position([position[i] - o for i, o in enumerate(self.OFFSET)])
    self.tilt, self.rot = self.LIGHT_CAM.point_at(position)
    self.cast_shader = Shader("shadowcast")


  def move_light(self, position):
    self.LIGHT_CAM.reset()
    self.LIGHT_CAM.rotate(self.tilt, self.rot, 0)
    self.LIGHT_CAM.position([position[i] - o for i, o in enumerate(self.OFFSET)])


  def start_cast(self, position=None):
    if position is not None:
      self.move_light(position)
    super(ShadowCaster, self)._start()


  def cast_shadow(self, shape):
    shape.draw(shader=self.cast_shader, light_camera=self.LIGHT_CAM)


  def end_cast(self):
    super(ShadowCaster, self)._end()

    
  def draw_shadow(self):
    self.emap.draw(shader=self.dshader)


  def draw_tree(self, tree, shader):
    tree.draw(shader, [self])
Ejemplo n.º 16
0
  def _loop_begin(self):
    # TODO(rec):  check if the window was resized and resize it, removing
    # code from MegaStation to here.
    self.clear()
    with self.lock:
      self.sprites_to_load, to_load = set(), self.sprites_to_load
      self.sprites.extend(to_load)
    self._for_each_sprite(lambda s: s.load_opengl(), to_load)

    if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
      from pi3d.Camera import Camera
      camera = Camera.instance()
      if camera:
        camera.was_moved = False
Ejemplo n.º 17
0
  def _loop_begin(self):
    # TODO(rec):  check if the window was resized and resize it, removing
    # code from MegaStation to here.
    self.clear()
    with self.lock:
      self.sprites_to_load, to_load = set(), self.sprites_to_load
      self.sprites.extend(to_load)
    self._for_each_sprite(lambda s: s.load_opengl(), to_load)

    if MARK_CAMERA_CLEAN_ON_EACH_LOOP:
      from pi3d.Camera import Camera
      camera = Camera.instance()
      if camera:
        camera.was_moved = False
Ejemplo n.º 18
0
 def __init__(self, emap, light):
     """ calls Texture.__init__ but doesn't need to set file name as
 texture generated from the framebuffer
 """
     super(ShadowCaster, self).__init__("shadow_caster")
     # load shader for casting shadows and camera
     self.cshader = Shader("uv_flat")
     self.mshader = Shader("mat_flat")
     # keep copy of ElevationMap
     self.emap = emap
     self.emap.set_material((0.0, 0.0, 0.0))  # hide bits below ground
     # TODO doesn't cope with  z light positions
     self.eye = [-500 * i for i in light.lightpos]  # good distance away
     if self.eye[1] <= 0:  # must have +ve y
         self.eye[1] = 500.0
     if abs(self.eye[0]) > abs(self.eye[2]):  # x val is bigger than z val
         # change scale so map just fits on screen
         if self.eye[0] < 0:
             su, sv = 1.0, 1.0
         else:
             su, sv = -1.0, -1.0
         self.scaleu = float(self.iy) / self.emap.width
         self.scalev = float(self.ix) / self.emap.depth
         self.eye[2] = 0
         self.scaleu = self.scaleu / self.eye[1] * float(self.eye[0] ** 2 + self.eye[1] ** 2) ** 0.5
         self.emap.unif[50] = 1.0  # orientation flag
         self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / float(self.eye[1])  # height adjustment
     else:
         # change scale so map just fits on screen
         if self.eye[2] < 0:
             su, sv = 1.0, -1.0
         else:
             su, sv = -1.0, 1.0
         self.scaleu = float(self.iy) / self.emap.depth
         self.scalev = float(self.ix) / self.emap.width
         self.eye[0] = 0
         self.scaleu = self.scaleu / self.eye[1] * float(self.eye[2] ** 2 + self.eye[1] ** 2) ** 0.5
         self.emap.unif[50] = 0.0
         self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / float(self.eye[1])
     if abs(self.scaleu) > abs(self.scalev):
         self.scale = 3.0 * self.scalev  # multiplication factor to reduce pixeliness
     else:
         self.scale = 3.0 * self.scaleu
     self.scaleu = su * self.scale / self.scaleu  # reused later in end_cast
     self.scalev = sv * self.scale / self.scalev
     self.camera0 = Camera()  # default instance created as normal, just in case!
     self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
     # load shader for drawing map with shadows
     self.dshader = Shader("shadowcast")
class ShadowCaster(OffScreenTexture):
    """For creating a depth-of-field blurring effect on selected objects"""
    def __init__(self, position, light, scale=10.0, ix=None, iy=None):
        """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
        super(ShadowCaster, self).__init__("shadow_caster")

        self.LIGHT_CAM = Camera(is_3d=False, scale=scale)
        l_p = light.lightpos
        l_len = (l_p[0]**2 + l_p[1]**2 + l_p[2]**2)**0.5
        self.OFFSET = [200.0 * i / l_len for i in l_p]
        self.OFFSET[0] = -self.OFFSET[0]
        self.OFFSET[2] = -self.OFFSET[2]
        self.LIGHT_CAM.position(
            [position[i] - o for i, o in enumerate(self.OFFSET)])
        self.tilt, self.rot = self.LIGHT_CAM.point_at(position)
        self.cast_shader = Shader("shadowcast")

    def move_light(self, position):
        self.LIGHT_CAM.reset()
        self.LIGHT_CAM.rotate(self.tilt, self.rot, 0)
        self.LIGHT_CAM.position(
            [position[i] - o for i, o in enumerate(self.OFFSET)])

    def start_cast(self, position=None):
        if position is not None:
            self.move_light(position)
        super(ShadowCaster, self)._start()

    def cast_shadow(self, shape):
        shape.draw(shader=self.cast_shader, light_camera=self.LIGHT_CAM)

    def end_cast(self):
        super(ShadowCaster, self)._end()

    def draw_shadow(self):
        self.emap.draw(shader=self.dshader)

    def draw_tree(self, tree, shader):
        tree.draw(shader, [self])
Ejemplo n.º 20
0
Archivo: Shape.py Proyecto: tipam/pi3d
 def rotate_to_direction(self, direction, forward=[0.0, 0.0, 1.0]):
   """ works out the XYZ euler rotations to rotate this shape from
   forward to direction vectors
   
   Arguments:
     *direction*
       3vector tuple, array or numpy array
     *forward*
       3vector, usually +ve z direction
   """
   if type(direction) is not np.ndarray:
     direction = np.array(direction)
   if type(forward) is not np.ndarray:
     forward = np.array(forward)
   if self._camera is None:
     self._camera = Camera.instance() # TODO may be issues doing this not in main thread (otherwise why not in Shape.__init__()?)
   rot_mtrix = self._camera.matrix_from_two_vectors(forward, direction)
   rot_euler = self._camera.euler_angles(rot_mtrix)
   self.rotateToX(-rot_euler[0]) # unclear why x and y need to be -ve
   self.rotateToY(-rot_euler[1]) # something to do with sense of rotation of camera
   self.rotateToZ(rot_euler[2])
Ejemplo n.º 21
0
  def draw(self, shader=None, txtrs=None, ntl=None, shny=None, camera=None):
    """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
    from pi3d.Camera import Camera

    camera = camera or self._camera or Camera.instance()
    shader = shader or self.shader
    shader.use()

    if self.MFlg == True:
      # Calculate rotation and translation matrix for this model using numpy.
      self.MRaw = dot(self.tr2,
        dot(self.scl,
            dot(self.roy,
                dot(self.rox,
                    dot(self.roz, self.tr1)))))
      self.M[0:16] = self.MRaw.ravel()
      self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()
      self.MFlg = False

    elif camera.was_moved:
      # Only do this if it's not done because model moved.
      self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()

    if camera.was_moved:
      self.unif[18:21] = camera.eye[0:3]

    opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2,
                                ctypes.c_int(0),
                                ctypes.byref(self.M))

    opengles.glUniform3fv(shader.unif_unif, 20, ctypes.byref(self.unif))
    for b in self.buf:
      # Shape.draw has to be passed either parameter == None or values to pass
      # on.
      b.draw(shader, txtrs, ntl, shny)
Ejemplo n.º 22
0
 def rotate_to_direction(self, direction, forward=[0.0, 0.0, 1.0]):
     """ works out the XYZ euler rotations to rotate this shape from
 forward to direction vectors
 
 Arguments:
   *direction*
     3vector tuple, array or numpy array
   *forward*
     3vector, usually +ve z direction
 """
     if type(direction) is not np.ndarray:
         direction = np.array(direction)
     if type(forward) is not np.ndarray:
         forward = np.array(forward)
     if self._camera is None:
         self._camera = Camera.instance(
         )  # TODO may be issues doing this not in main thread (otherwise why not in Shape.__init__()?)
     rot_mtrix = self._camera.matrix_from_two_vectors(forward, direction)
     rot_euler = self._camera.euler_angles(rot_mtrix)
     self.rotateToX(-rot_euler[0])  # unclear why x and y need to be -ve
     self.rotateToY(
         -rot_euler[1])  # something to do with sense of rotation of camera
     self.rotateToZ(rot_euler[2])
Ejemplo n.º 23
0
  def __init__(self, shader="uv_flat", mipmap=False, separation=0.4):
    """ 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

      *separation*
        distance between the two camera positions - how wide apart the
        eye views are.
    """
    # load shader
    self.shader = Shader(shader)
    self.camera_3d = Camera()
    self.camera_2d = Camera(is_3d=False)
    self.offs = separation / 2.0
    self.textures = []
    self.sprites = []
    self.tex_list = []
    for i in range(2):
      self.textures.append(OffScreenTexture(name="bin"))
      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, x=-ix/2.0 + i*ix, w=ix, h=iy, flip=True))
      self.sprites[i].set_offset((i * 0.5 - 0.25, 0.0))
      self.textures[i].alpha = False
      self.textures[i].blend = True
      self.textures[i].mipmap = mipmap
      self.tex_list.append([self.textures[i]])
Ejemplo n.º 24
0
    def draw(self, shader=None, txtrs=None, ntl=None, shny=None, camera=None):
        """If called without parameters, there has to have been a previous call to
    set_draw_details() for each Buffer in buf[].
    NB there is no facility for setting umult and vmult with draw: they must be
    set using set_draw_details or Buffer.set_draw_details.
    """
        from pi3d.Camera import Camera

        camera = camera or self._camera or Camera.instance()
        shader = shader or self.shader
        shader.use()

        if self.MFlg == True:
            # Calculate rotation and translation matrix for this model using numpy.
            self.MRaw = dot(
                self.tr2,
                dot(self.scl,
                    dot(self.roy, dot(self.rox, dot(self.roz, self.tr1)))))
            self.M[0:16] = self.MRaw.ravel()
            self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()
            self.MFlg = False

        elif camera.was_moved:
            # Only do this if it's not done because model moved.
            self.M[16:32] = dot(self.MRaw, camera.mtrx).ravel()

        if camera.was_moved:
            self.unif[18:21] = camera.eye[0:3]

        opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2,
                                    ctypes.c_int(0), ctypes.byref(self.M))

        opengles.glUniform3fv(shader.unif_unif, 20, ctypes.byref(self.unif))
        for b in self.buf:
            # Shape.draw has to be passed either parameter == None or values to pass
            # on.
            b.draw(shader, txtrs, ntl, shny)
Ejemplo n.º 25
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 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

      *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:
            self.shader = Shader(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.shader = Shader("2d_flat")
        self.camera_3d = Camera()
        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)
Ejemplo n.º 26
0
class StereoCam(object):
    """For creating an apparatus with two sprites to hold left and right
  eye views.

  This Class is used to hold the 3D Camera which should be used to draw
  the 3D objects. It also holds a 2D Camera for drawing the Sprites"""

    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 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

      *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:
            self.shader = Shader(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.shader = Shader("2d_flat")
        self.camera_3d = Camera()
        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)

    def move_camera(self, position, rot, tilt, roll=0.0, absolute=True):
        """ Arguments:
    
      *position*
        array [x,y,z]

      *rot, tilt, roll*
        rotations about y, x, z axis (yes it's not entirely logical for position
        to be an array and orientation three values but it's too late to change!)

      *absolute*
        if set to False then the rotations are treated as relative to the
        rotated frame of reference i.e. as if signals from VR headset 3
        axis gyro.
    """
        self.camera_3d.rotate(tilt, rot, roll)
        self.camera_3d.position(position)
        self.camera_3d.absolute = absolute

    def start_capture(self, side):
        """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display.

      *side*
        Either 0 or 1 to determine stereoscopic view
    """
        self.camera_3d.reset()
        offs = -self.offs if side == 0 else self.offs
        self.camera_3d.offset([offs, 0.0, 0.0])
        # self.camera_3d.mtrx = np.dot(self.forMtrx, self.camera_3d.mtrx)
        # self.camera_3d.position(self.position)
        tex = self.textures[side]
        tex._start()
        if self.interlace <= 0:
            xx = tex.ix / 4.0  # draw the middle only - half width
            yy = 0
            ww = tex.ix / 2.0
            hh = tex.iy
            opengles.glEnable(GL_SCISSOR_TEST)
            opengles.glScissor(
                ctypes.c_int(int(xx)), ctypes.c_int(int(yy)), ctypes.c_int(int(ww)), ctypes.c_int(int(hh))
            )

    def end_capture(self, side):
        """ stop capturing to texture and resume normal rendering to default
    """
        self.textures[side]._end()
        if self.interlace <= 0:
            opengles.glDisable(GL_SCISSOR_TEST)

    def draw(self):
        """ draw the shape using the saved texture
    """
        if self.interlace <= 0:
            for i in range(2):
                self.sprites[i].draw(self.shader, [self.tex_list[i]], 0.0, 0.0, self.camera_2d)
        else:
            self.sprites[0].draw(self.shader, self.tex_list, 0.0, 0.0, self.camera_2d)

    def get_direction(self):
        return self.camera_3d.get_direction()
Ejemplo n.º 27
0
class StereoCam(object):
  """For creating an apparatus with two sprites to hold left and right
  eye views.

  This Class is used to hold the 3D Camera which should be used to draw
  the 3D objects. It also holds a 2D Camera for drawing the Sprites"""
  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)

  def move_camera(self, position, rot, tilt, roll=0.0, absolute=True):
    ''' Arguments:
    
      *position*
        array [x,y,z]

      *rot, tilt, roll*
        rotations about y, x, z axis (yes it's not entirely logical for position
        to be an array and orientation three values but it's too late to change!)

      *absolute*
        if set to False then the rotations are treated as relative to the
        rotated frame of reference i.e. as if signals from VR headset 3
        axis gyro.
    '''
    self.camera_3d.rotate(tilt, rot, roll)
    self.camera_3d.position(position)
    self.camera_3d.absolute = absolute
    
  def start_capture(self, side):
    """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display.

      *side*
        Either 0 or 1 to determine stereoscopic view
    """
    self.camera_3d.reset()
    offs = -self.offs if side == 0 else self.offs
    self.camera_3d.offset([offs, 0.0, 0.0])
    #self.camera_3d.mtrx = np.dot(self.forMtrx, self.camera_3d.mtrx)
    #self.camera_3d.position(self.position)
    tex = self.textures[side]
    tex._start()
    if self.interlace <= 0:
      xx = tex.ix / 4.0 # draw the middle only - half width
      yy = 0
      ww = tex.ix / 2.0
      hh = tex.iy
      opengles.glEnable(GL_SCISSOR_TEST)
      opengles.glScissor(GLint(int(xx)), GLint(int(yy)),
                    GLsizei(int(ww)), GLsizei(int(hh)))

  def end_capture(self, side):
    """ stop capturing to texture and resume normal rendering to default
    """
    self.textures[side]._end()
    if self.interlace <= 0:
      opengles.glDisable(GL_SCISSOR_TEST)

  def draw(self):
    """ draw the shape using the saved texture
    """
    if self.interlace <= 0:
      for i in range(2):
        self.sprites[i].draw(self.shader, [self.tex_list[i].color], 0.0, 0.0, self.camera_2d)
    else:
      self.sprites[0].draw(self.shader, [t.color for t in self.tex_list], 0.0, 0.0, self.camera_2d)
      
  def get_direction(self):
    return self.camera_3d.get_direction()
Ejemplo n.º 28
0
class ShadowCaster(OffScreenTexture):
  """For creating a depth-of-field blurring effect on selected objects"""
  def __init__(self, emap, light):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
    super(ShadowCaster, self).__init__("shadow_caster")
    # load shader for casting shadows and camera
    self.cshader = Shader("uv_flat")
    self.mshader = Shader("mat_flat")
    # keep copy of ElevationMap
    self.emap = emap
    self.emap.set_material((0.0, 0.0, 0.0)) # hide bits below ground
    #TODO doesn't cope with  z light positions
    self.eye = [-500.0 * i for i in light.lightpos] # good distance away
    if self.eye[1] <= 0: # must have +ve y
      self.eye[1] = 500.0
    if abs(self.eye[0]) > abs(self.eye[2]): #x val is bigger than z val
      #change scale so map just fits on screen
      if self.eye[0] < 0:
        su, sv  = 1.0, 1.0
      else:
        su, sv  = -1.0, -1.0
      self.scaleu = float(self.iy) / self.emap.width
      self.scalev = float(self.ix)/ self.emap.depth
      self.eye[2] = 0
      self.scaleu = self.scaleu / self.eye[1] * (self.eye[0]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 1.0 #orientation flag
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / self.eye[1] #height adjustment
    else:
      #change scale so map just fits on screen
      if self.eye[2] < 0:
        su, sv  = 1.0, -1.0
      else:
        su, sv  = -1.0, 1.0
      self.scaleu = float(self.iy) / self.emap.depth
      self.scalev = float(self.ix)/ self.emap.width
      self.eye[0] = 0
      self.scaleu = self.scaleu / self.eye[1] * (self.eye[2]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 0.0
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / self.eye[1]
    if abs(self.scaleu) > abs(self.scalev):
      self.scale = 3.0 * self.scalev # multiplication factor to reduce pixeliness
    else:
      self.scale = 3.0 * self.scaleu
    self.scaleu = su * self.scale / self.scaleu # reused later in end_cast
    self.scalev = sv * self.scale / self.scalev
    self.camera0 = Camera() # default instance created as normal, just in case!
    self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
    # load shader for drawing map with shadows
    self.dshader = Shader("shadowcast")

  def start_cast(self, location=(0.0, 0.0,  0.0)):
    """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display. If you want blurred
    edges you will have to capture the rendering of an object and its
    background then re-draw them using the blur() method. Large objects
    will obviously take a while to draw and re-draw
    """
    opengles.glClearColor(ctypes.c_float(0.0), ctypes.c_float(0.0), 
                        ctypes.c_float(0.0), ctypes.c_float(1.0))
    super(ShadowCaster, self)._start()
    self.camera.reset(is_3d=False, scale=self.scale)
    self.camera.position((location[0], 0, location[2]))
    self.location = location

  def end_cast(self):
    """ stop capturing to texture and resume normal rendering to default
    """
    #draw the actual map
    self.emap.draw(shader=self.mshader, camera=self.camera)
    super(ShadowCaster, self)._end()
    # set third texture to this ShadowCaster texture
    texs = self.emap.buf[0].textures
    if len(texs) == 2:
      texs.append(self)
    else:
      texs[2] = self
    # change background back to blue
    opengles.glClearColor(ctypes.c_float(0.4), ctypes.c_float(0.8), 
                        ctypes.c_float(0.8), ctypes.c_float(1.0))
    # work out left, top, right, bottom for shader
    self.emap.unif[48] = 0.5 * (1.0 + self.scaleu) # left [16][0]
    self.emap.unif[49] = 0.5 * (1.0 + self.scalev) # top [16][1]
    self.emap.unif[51] = 1.0 - self.emap.unif[48] # right [17][0]
    self.emap.unif[52] = 1.0 - self.emap.unif[49] # bottom [17][1]
    
    du = float(self.location[0] / self.emap.width)
    dv = float(self.location[2] / self.emap.depth)
    self.emap.unif[48] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
    self.emap.unif[49] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)
    self.emap.unif[51] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
    self.emap.unif[52] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)

  def add_shadow(self, shape):
    shape.draw(shader=self.cshader, camera=self.camera)
    
  def draw_shadow(self):
    self.emap.draw(shader=self.dshader)
Ejemplo n.º 29
0
  def __init__(self, emap, light):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
    super(ShadowCaster, self).__init__("shadow_caster")
    from pi3d.Display import Display
    self.ix, self.iy = Display.INSTANCE.width, Display.INSTANCE.height
    self.im = Image.new("RGBA",(self.ix, self.iy))
    self.image = self.im.convert("RGBA").tostring('raw', "RGBA")
    self.alpha = True
    self.blend = False

    self._tex = ctypes.c_int()
    self.framebuffer = (ctypes.c_int * 1)()
    opengles.glGenFramebuffers(1, self.framebuffer)
    self.depthbuffer = (ctypes.c_int * 1)()
    opengles.glGenRenderbuffers(1, self.depthbuffer)

    # load shader for casting shadows and camera
    self.cshader = Shader("shaders/uv_flat")
    self.mshader = Shader("shaders/mat_flat")
    # keep copy of ElevationMap
    self.emap = emap
    self.emap.set_material((0.0, 0.0, 0.0)) # hide bits below ground
    #TODO doesn't cope with  z light positions
    self.eye = [-500*i for i in light.lightpos] # good distance away
    if self.eye[1] <= 0: # must have +ve y
      self.eye[1] = 500.0
    if abs(self.eye[0]) > abs(self.eye[2]): #x val is bigger than z val
      #change scale so map just fits on screen
      if self.eye[0] < 0:
        su, sv  = 1.0, 1.0
      else:
        su, sv  = -1.0, -1.0
      self.scaleu = float(self.iy) / self.emap.width
      self.scalev = float(self.ix)/ self.emap.depth
      self.eye[2] = 0
      self.scaleu = self.scaleu / self.eye[1] * float(self.eye[0]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 1.0 #orientation flag
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / float(self.eye[1]) #height adjustment
    else:
      #change scale so map just fits on screen
      if self.eye[2] < 0:
        su, sv  = 1.0, -1.0
      else:
        su, sv  = -1.0, 1.0
      self.scaleu = float(self.iy) / self.emap.depth
      self.scalev = float(self.ix)/ self.emap.width
      self.eye[0] = 0
      self.scaleu = self.scaleu / self.eye[1] * float(self.eye[2]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 0.0
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / float(self.eye[1])
    if abs(self.scaleu) > abs(self.scalev):
      self.scale = 3.0 * self.scalev # multiplication factor to reduce pixeliness
    else:
      self.scale = 3.0 * self.scaleu
    self.scaleu = su * self.scale / self.scaleu # reused later in end_cast
    self.scalev = sv * self.scale / self.scalev
    self.camera0 = Camera() # default instance created as normal, just in case!
    self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
    # load shader for drawing map with shadows
    self.dshader = Shader("shaders/shadowcast")
Ejemplo n.º 30
0
class StereoCam(object):
  """For creating an apparatus with two sprites to hold left and right
  eye views.
  This Class is used to hold the 3D Camera which should be used to draw
  the 3D objects. It also holds a 2D Camera for drawing the Sprites"""
  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 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
      *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:
      self.shader = Shader(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.shader = Shader("2d_flat")
    self.camera_3d = Camera()
    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])

  def move_camera(self, position, rot, tilt):
    self.camera_3d.reset()
    self.camera_3d.rotate(tilt, rot, 0)
    self.camera_3d.position(position)

  def start_capture(self, side):
    """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display.
      *side*
        Either 0 or 1 to determine stereoscopic view
    """
    offs = -self.offs if side == 0 else self.offs
    self.camera_3d.position((self.camera_3d.mtrx[2,3] * offs, 0,
                            -self.camera_3d.mtrx[0,3] * offs))
    tex = self.textures[side]
    tex._start()
    if self.interlace <= 0:
      xx = tex.ix / 4.0 # draw the middle only - half width
      yy = 0
      ww = tex.ix / 2.0
      hh = tex.iy
      opengles.glEnable(GL_SCISSOR_TEST)
      opengles.glScissor(ctypes.c_int(int(xx)), ctypes.c_int(int(yy)),
                    ctypes.c_int(int(ww)), ctypes.c_int(int(hh)))

  def end_capture(self, side):
    """ stop capturing to texture and resume normal rendering to default
    """
    self.textures[side]._end()
    if self.interlace <= 0:
      opengles.glDisable(GL_SCISSOR_TEST)

  def draw(self):
    """ draw the shape using the saved texture
    """
    if self.interlace <= 0:
      for i in range(2):
        self.sprites[i].draw(self.shader, [self.tex_list[i]], 0.0, 0.0, self.camera_2d)
    else:
      self.sprites[0].draw(self.shader, self.tex_list, 0.0, 0.0, self.camera_2d)
Ejemplo n.º 31
0
 def cameraY(self,y):
     self.vrcamyloc = y	
     from pi3d.Camera import Camera
     vrcamera = Camera.instance()
     if vrcamera:
         vrcamera.position((self.vrcamxloc,self.vrcamyloc,1.0))
Ejemplo n.º 32
0
class ShadowCaster(OffScreenTexture):
    """For creating a depth-of-field blurring effect on selected objects"""

    def __init__(self, emap, light):
        """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
        super(ShadowCaster, self).__init__("shadow_caster")
        # load shader for casting shadows and camera
        self.cshader = Shader("uv_flat")
        self.mshader = Shader("mat_flat")
        # keep copy of ElevationMap
        self.emap = emap
        self.emap.set_material((0.0, 0.0, 0.0))  # hide bits below ground
        # TODO doesn't cope with  z light positions
        self.eye = [-500 * i for i in light.lightpos]  # good distance away
        if self.eye[1] <= 0:  # must have +ve y
            self.eye[1] = 500.0
        if abs(self.eye[0]) > abs(self.eye[2]):  # x val is bigger than z val
            # change scale so map just fits on screen
            if self.eye[0] < 0:
                su, sv = 1.0, 1.0
            else:
                su, sv = -1.0, -1.0
            self.scaleu = float(self.iy) / self.emap.width
            self.scalev = float(self.ix) / self.emap.depth
            self.eye[2] = 0
            self.scaleu = self.scaleu / self.eye[1] * float(self.eye[0] ** 2 + self.eye[1] ** 2) ** 0.5
            self.emap.unif[50] = 1.0  # orientation flag
            self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / float(self.eye[1])  # height adjustment
        else:
            # change scale so map just fits on screen
            if self.eye[2] < 0:
                su, sv = 1.0, -1.0
            else:
                su, sv = -1.0, 1.0
            self.scaleu = float(self.iy) / self.emap.depth
            self.scalev = float(self.ix) / self.emap.width
            self.eye[0] = 0
            self.scaleu = self.scaleu / self.eye[1] * float(self.eye[2] ** 2 + self.eye[1] ** 2) ** 0.5
            self.emap.unif[50] = 0.0
            self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / float(self.eye[1])
        if abs(self.scaleu) > abs(self.scalev):
            self.scale = 3.0 * self.scalev  # multiplication factor to reduce pixeliness
        else:
            self.scale = 3.0 * self.scaleu
        self.scaleu = su * self.scale / self.scaleu  # reused later in end_cast
        self.scalev = sv * self.scale / self.scalev
        self.camera0 = Camera()  # default instance created as normal, just in case!
        self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
        # load shader for drawing map with shadows
        self.dshader = Shader("shadowcast")

    def start_cast(self, location=(0.0, 0.0, 0.0)):
        """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display. If you want blurred
    edges you will have to capture the rendering of an object and its
    background then re-draw them using the blur() method. Large objects
    will obviously take a while to draw and re-draw
    """
        opengles.glClearColor(ctypes.c_float(0.0), ctypes.c_float(0.0), ctypes.c_float(0.0), ctypes.c_float(1.0))
        super(ShadowCaster, self)._start()
        self.camera.reset(is_3d=False, scale=self.scale)
        self.camera.position((location[0], 0, location[2]))
        self.location = location

    def end_cast(self):
        """ stop capturing to texture and resume normal rendering to default
    """
        # draw the actual map
        self.emap.draw(shader=self.mshader, camera=self.camera)
        super(ShadowCaster, self)._end()
        # set third texture to this ShadowCaster texture
        texs = self.emap.buf[0].textures
        if len(texs) == 2:
            texs.append(self)
        else:
            texs[2] = self
        # change background back to blue
        opengles.glClearColor(ctypes.c_float(0.4), ctypes.c_float(0.8), ctypes.c_float(0.8), ctypes.c_float(1.0))
        # work out left, top, right, bottom for shader
        self.emap.unif[48] = 0.5 * (1.0 + self.scaleu)  # left [16][0]
        self.emap.unif[49] = 0.5 * (1.0 + self.scalev)  # top [16][1]
        self.emap.unif[51] = 1.0 - self.emap.unif[48]  # right [17][0]
        self.emap.unif[52] = 1.0 - self.emap.unif[49]  # bottom [17][1]

        du = float(self.location[0] / self.emap.width)
        dv = float(self.location[2] / self.emap.depth)
        self.emap.unif[48] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
        self.emap.unif[49] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)
        self.emap.unif[51] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
        self.emap.unif[52] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)

    def add_shadow(self, shape):
        shape.draw(shader=self.cshader, camera=self.camera)

    def draw_shadow(self):
        self.emap.draw(shader=self.dshader)
Ejemplo n.º 33
0
Archivo: Pong.py Proyecto: Arexxk/pi3d
from pi3d.shape.Sphere import Sphere

from pi3d.util.String import String
from pi3d.util.Screenshot import screenshot
from pi3d.util.Defocus import Defocus

#helpful messages
print("############################################################")
print("Mouse to move left and right and up and down")
print("############################################################")
print()

# Setup display and initialise pi3d
DISPLAY = Display.create(x=200, y=200, frames_per_second=20)
DISPLAY.set_background(0.4,0.8,0.8,1) # r,g,b,alpha
camera = Camera((0, 0, 0), (0, 0, -1), (1, 1000, 30.0, DISPLAY.width/DISPLAY.height))
light = Light((10, -10, 20))
# load shader
shader = Shader("shaders/uv_reflect")
flatsh = Shader("shaders/uv_flat")
defocus = Defocus()
#========================================

# Setting 2nd param to True renders 'True' Blending
# (this can be changed later to 'False' with 'rockimg2.blend = False')
groundimg = Texture("textures/stripwood.jpg")
monstimg = Texture("textures/pong3.png")
ballimg = Texture("textures/pong2.jpg")

# environment cube
ectex = Texture("textures/ecubes/skybox_stormydays.jpg")
Ejemplo n.º 34
0
    def draw(self) -> None:
        import numpy as np
        from scipy.ndimage.filters import gaussian_filter
        from pi3d.Camera import Camera
        from pi3d.constants import (
            opengles,
            GL_SRC_ALPHA,
            GL_ONE_MINUS_SRC_ALPHA,
            GLsizei,
            GLboolean,
            GLint,
            GL_FLOAT,
            GL_ARRAY_BUFFER,
            GL_UNSIGNED_SHORT,
            GL_TEXTURE_2D,
            GL_UNSIGNED_BYTE,
        )

        time_logging = False

        if self.should_prepare:
            self._prepare()

        if self.lights.alarm_program.factor != -1:
            self.alarm_factor = max(0.001, self.lights.alarm_program.factor)
        else:
            self.alarm_factor = 0

        then = time.time()

        self.display.loop_running()
        now = self.display.time
        self.time_delta = now - self.last_loop
        self.last_loop = now
        self.time_elapsed += self.time_delta

        if time_logging:
            print(f"{time.time() - then} main loop")
            then = time.time()

        # use a sliding window to smooth the spectrum with a gauss function
        # truncating does not save significant time (~3% for this step)

        # new_frame = np.array(self.cava.current_frame, dtype="float32")
        new_frame = gaussian_filter(self.cava.current_frame, sigma=1.5, mode="nearest")
        new_frame = new_frame[self.SPECTRUM_CUT : -self.SPECTRUM_CUT]
        new_frame = -0.5 * new_frame ** 3 + 1.5 * new_frame
        new_frame *= 255
        current_frame = new_frame

        if time_logging:
            print(f"{time.time() - then} spectrum smoothing")
            then = time.time()

        # Value used for circle shake and background color cycle
        # select the first few values and compute their average
        bass_elements = math.ceil(self.BASS_MAX * self.cava.bars)
        self.bass_value = sum(current_frame[0:bass_elements]) / bass_elements / 255
        self.bass_value = max(self.bass_value, self.alarm_factor)
        self.total_bass = self.total_bass + self.bass_value
        # the fraction of time that there was bass
        self.bass_fraction = self.total_bass / self.time_elapsed / self.lights.UPS

        self.uniform_values = {
            48: self.width / self.scale,
            49: self.height / self.scale,
            50: self.scale,
            51: self.FFT_HIST,
            52: self.NUM_PARTICLES,
            53: self.PARTICLE_SPAWN_Z,
            54: self.time_elapsed,
            55: self.time_delta,
            56: self.alarm_factor,
            57: self.bass_value,
            58: self.total_bass,
            59: self.bass_fraction,
        }

        # start rendering to the smaller OffscreenTexture
        # we decrease the size of the texture so it only allocates that much memory
        # otherwise it would use as much as the displays size, negating its positive effect
        self.post.ix = int(self.post.ix / self.scale)
        self.post.iy = int(self.post.iy / self.scale)
        opengles.glViewport(
            GLint(0),
            GLint(0),
            GLsizei(int(self.width / self.scale)),
            GLsizei(int(self.height / self.scale)),
        )
        self.post._start()
        self.post.ix = self.width
        self.post.iy = self.height

        self._set_unif(self.background, [48, 49, 54, 56, 58])
        self.background.draw()

        if time_logging:
            print(f"{time.time() - then} background draw")
            then = time.time()

        # enable additive blending so the draw order of overlapping particles does not matter
        opengles.glBlendFunc(1, 1)

        self._set_unif(self.particle_sprite, [53, 54, 59])

        # copied code from pi3d.Shape.draw()
        # we don't need modelmatrices, normals ord textures and always blend
        self.particle_sprite.load_opengl()
        camera = Camera.instance()
        if not camera.mtrx_made:
            camera.make_mtrx()
        self.particle_sprite.MRaw = self.particle_sprite.tr1
        self.particle_sprite.M[0, :, :] = self.particle_sprite.MRaw[:, :]
        self.particle_sprite.M[1, :, :] = np.dot(
            self.particle_sprite.MRaw, camera.mtrx
        )[:, :]

        # Buffer.draw()
        buf = self.particle_sprite.buf[0]
        buf.load_opengl()
        shader = buf.shader
        shader.use()
        opengles.glUniformMatrix4fv(
            shader.unif_modelviewmatrix,
            GLsizei(2),
            GLboolean(0),
            self.particle_sprite.M.ctypes.data,
        )
        opengles.glUniform3fv(shader.unif_unif, GLsizei(20), self.particle_sprite.unif)
        buf._select()
        opengles.glVertexAttribPointer(
            shader.attr_vertex, GLint(3), GL_FLOAT, GLboolean(0), buf.N_BYTES, 0
        )
        opengles.glEnableVertexAttribArray(shader.attr_vertex)
        opengles.glVertexAttribPointer(
            shader.attr_texcoord, GLint(2), GL_FLOAT, GLboolean(0), buf.N_BYTES, 24
        )
        opengles.glEnableVertexAttribArray(shader.attr_texcoord)
        buf.disp.last_shader = shader
        opengles.glUniform3fv(shader.unif_unib, GLsizei(5), buf.unib)

        opengles.glBindBuffer(GL_ARRAY_BUFFER, self.instance_vbo)
        opengles.glDrawElementsInstanced(
            buf.draw_method,
            GLsizei(buf.ntris * 3),
            GL_UNSIGNED_SHORT,
            0,
            self.NUM_PARTICLES,
        )

        # restore normal blending
        opengles.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

        if time_logging:
            print(f"{time.time() - then} particle draw")
            then = time.time()

        # roll the history one further, insert the current one.
        # we use a texture with four channels eventhough we only need one, refer to this post:
        # https://community.khronos.org/t/updating-textures-per-frame/75020/3
        # basically the gpu converts it anyway, so other formats would be slower
        history = np.zeros(
            (self.FFT_HIST, self.cava.bars - 2 * self.SPECTRUM_CUT, 4), dtype="uint8"
        )
        self.fft = np.roll(self.fft, 1, 0)
        self.fft[0] = current_frame
        history[:, :, 0] = self.fft

        if time_logging:
            print(f"{time.time() - then} spectrum roll")
            then = time.time()

        # change the spectrum part of the texture (the lower 256xFFT_HIST pixels)
        opengles.glBindTexture(GL_TEXTURE_2D, self.dynamic_texture._tex)
        iformat = self.dynamic_texture._get_format_from_array(
            history, self.dynamic_texture.i_format
        )
        opengles.glTexSubImage2D(
            GL_TEXTURE_2D,
            0,
            0,
            self.dynamic_texture.ix,
            history.shape[1],
            history.shape[0],
            iformat,
            GL_UNSIGNED_BYTE,
            history.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte)),
        )

        if time_logging:
            print(f"{time.time() - then} glTexImage2D")
            then = time.time()

        self._set_unif(self.spectrum, [48, 49, 51, 52, 53, 54, 55, 57, 58])
        self.spectrum.draw()

        if time_logging:
            print(f"{time.time() - then} spectrum draw")
            then = time.time()

        self._set_unif(self.logo, [48, 49, 51, 54, 57, 58])
        self.logo.draw()

        if time_logging:
            print(f"{time.time() - then} logo draw")
            then = time.time()

        self._set_unif(self.after, [48, 49, 54, 57])
        self.after.draw()

        if time_logging:
            print(f"{time.time() - then} after draw")
            then = time.time()

        self.post._end()

        opengles.glViewport(
            GLint(0), GLint(0), GLsizei(self.width), GLsizei(self.height)
        )
        self._set_unif(self.post_sprite, [50])
        self.post_sprite.draw()

        if time_logging:
            print(f"{time.time() - then} post draw")
            print(f"scale: {self.scale}")
            print("=====")
Ejemplo n.º 35
0
class ShadowCaster(Texture):
  """For creating a depth-of-field blurring effect on selected objects"""
  def __init__(self, emap, light):
    """ calls Texture.__init__ but doesn't need to set file name as
    texture generated from the framebuffer
    """
    super(ShadowCaster, self).__init__("shadow_caster")
    from pi3d.Display import Display
    self.ix, self.iy = Display.INSTANCE.width, Display.INSTANCE.height
    self.im = Image.new("RGBA",(self.ix, self.iy))
    self.image = self.im.convert("RGBA").tostring('raw', "RGBA")
    self.alpha = True
    self.blend = False

    self._tex = ctypes.c_int()
    self.framebuffer = (ctypes.c_int * 1)()
    opengles.glGenFramebuffers(1, self.framebuffer)
    self.depthbuffer = (ctypes.c_int * 1)()
    opengles.glGenRenderbuffers(1, self.depthbuffer)

    # load shader for casting shadows and camera
    self.cshader = Shader("shaders/uv_flat")
    self.mshader = Shader("shaders/mat_flat")
    # keep copy of ElevationMap
    self.emap = emap
    self.emap.set_material((0.0, 0.0, 0.0)) # hide bits below ground
    #TODO doesn't cope with  z light positions
    self.eye = [-500*i for i in light.lightpos] # good distance away
    if self.eye[1] <= 0: # must have +ve y
      self.eye[1] = 500.0
    if abs(self.eye[0]) > abs(self.eye[2]): #x val is bigger than z val
      #change scale so map just fits on screen
      if self.eye[0] < 0:
        su, sv  = 1.0, 1.0
      else:
        su, sv  = -1.0, -1.0
      self.scaleu = float(self.iy) / self.emap.width
      self.scalev = float(self.ix)/ self.emap.depth
      self.eye[2] = 0
      self.scaleu = self.scaleu / self.eye[1] * float(self.eye[0]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 1.0 #orientation flag
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[0] / float(self.eye[1]) #height adjustment
    else:
      #change scale so map just fits on screen
      if self.eye[2] < 0:
        su, sv  = 1.0, -1.0
      else:
        su, sv  = -1.0, 1.0
      self.scaleu = float(self.iy) / self.emap.depth
      self.scalev = float(self.ix)/ self.emap.width
      self.eye[0] = 0
      self.scaleu = self.scaleu / self.eye[1] * float(self.eye[2]**2 + self.eye[1]**2)**0.5
      self.emap.unif[50] = 0.0
      self.emap.unif[53] = -3.0 * su / self.emap.width * self.eye[2] / float(self.eye[1])
    if abs(self.scaleu) > abs(self.scalev):
      self.scale = 3.0 * self.scalev # multiplication factor to reduce pixeliness
    else:
      self.scale = 3.0 * self.scaleu
    self.scaleu = su * self.scale / self.scaleu # reused later in end_cast
    self.scalev = sv * self.scale / self.scalev
    self.camera0 = Camera() # default instance created as normal, just in case!
    self.camera = Camera(is_3d=False, eye=self.eye, scale=self.scale)
    # load shader for drawing map with shadows
    self.dshader = Shader("shaders/shadowcast")

  def _load_disk(self):
    """ have to override this
    """

  def start_cast(self, location=(0.0, 0.0,  0.0)):
    """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display. If you want blurred
    edges you will have to capture the rendering of an object and its
    background then re-draw them using the blur() method. Large objects
    will obviously take a while to draw and re-draw
    """
    opengles.glBindFramebuffer(GL_FRAMEBUFFER, self.framebuffer)
    opengles.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_TEXTURE_2D, self._tex.value, 0)
    #thanks to PeterO c.o. RPi forum for pointing out missing depth attchmnt
    opengles.glBindRenderbuffer(GL_RENDERBUFFER, self.depthbuffer)
    opengles.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
                self.ix, self.iy)
    opengles.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                GL_RENDERBUFFER, self.depthbuffer)
    opengles.glClearColor(ctypes.c_float(0.0), ctypes.c_float(0.0), 
                        ctypes.c_float(0.0), ctypes.c_float(1.0))
    opengles.glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)

    opengles.glEnable(GL_TEXTURE_2D)
    opengles.glActiveTexture(0)
    self.camera.reset(is_3d=False, scale=self.scale)
    self.camera.position((location[0], 0, location[2]))
    self.location = location

  def end_cast(self):
    """ stop capturing to texture and resume normal rendering to default
    """
    #draw the actual map
    self.emap.draw(shader=self.mshader, camera=self.camera)
    opengles.glBindTexture(GL_TEXTURE_2D, 0)
    opengles.glBindFramebuffer(GL_FRAMEBUFFER, 0)
    # set third texture to this ShadowCaster texture
    texs = self.emap.buf[0].textures
    if len(texs) == 2:
      texs.append(self)
    else:
      texs[2] = self
    # change background back to blue
    opengles.glClearColor(ctypes.c_float(0.4), ctypes.c_float(0.8), 
                        ctypes.c_float(0.8), ctypes.c_float(1.0))
    # work out left, top, right, bottom for shader
    self.emap.unif[48] = 0.5 * (1.0 + self.scaleu) # left [16][0]
    self.emap.unif[49] = 0.5 * (1.0 + self.scalev) # top [16][1]
    self.emap.unif[51] = 1.0 - self.emap.unif[48] # right [17][0]
    self.emap.unif[52] = 1.0 - self.emap.unif[49] # bottom [17][1]
    
    du = float(self.location[0] / self.emap.width)
    dv = float(self.location[2] / self.emap.depth)
    self.emap.unif[48] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
    self.emap.unif[49] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)
    self.emap.unif[51] -= self.scaleu * (du if self.emap.unif[50] == 1.0 else dv)
    self.emap.unif[52] += self.scalev * (dv if self.emap.unif[50] == 1.0 else du)

  def add_shadow(self, shape):
    shape.draw(shader=self.cshader, camera=self.camera)
    
  def draw_shadow(self):
    self.emap.draw(shader=self.dshader)
    
  def delete_buffers(self):
    opengles.glDeleteFramebuffers(1, self.framebuffer)
    opengles.glDeleteRenderbuffers(1, self.depthbuffer)
Ejemplo n.º 36
0
Archivo: Blur.py Proyecto: Arexxk/pi3d
from pi3d.Light import Light
from pi3d.Shader import Shader

from pi3d.util.String import String
from pi3d.util.Ttffont import Ttffont
from pi3d.util.Defocus import Defocus
from pi3d.util.Screenshot import screenshot
from pi3d.shape.MergeShape import MergeShape
from pi3d.shape.Sphere import Sphere
from pi3d.shape.Sprite import Sprite

# Setup display and initialise pi3d
DISPLAY = Display.create(x=10, y=10, w=900, h=600, frames_per_second=25)
DISPLAY.set_background(0.4, 0.6, 0.8, 1.0)      # r,g,b,alpha

persp_cam = Camera.instance() # default instance camera perspecive view
ortho_cam = Camera(is_3d=False) # 2d orthographic view camera

#setup textures, light position and initial model position
Light((0, 5, 0))
#create shaders
shader = Shader("shaders/uv_reflect")
flatsh = Shader("shaders/uv_flat")
defocus = Defocus()

#Create textures
shapeimg = Texture("textures/straw1.jpg")
shapebump = Texture("textures/floor_nm.jpg", True)
shapeshine = Texture("textures/pong3.png")

#Create shape
Ejemplo n.º 37
0
from pi3d.Light import Light
from pi3d.Shader import Shader

from pi3d.util.String import String
from pi3d.util.Ttffont import Ttffont
from pi3d.util.Defocus import Defocus
from pi3d.util.Screenshot import screenshot
from pi3d.shape.MergeShape import MergeShape
from pi3d.shape.Sphere import Sphere
from pi3d.shape.Sprite import Sprite

# Setup display and initialise pi3d
DISPLAY = Display.create(x=10, y=10, w=900, h=600, frames_per_second=25)
DISPLAY.set_background(0.4, 0.6, 0.8, 1.0)  # r,g,b,alpha

persp_cam = Camera.instance()  # default instance camera perspecive view
ortho_cam = Camera(is_3d=False)  # 2d orthographic view camera

#setup textures, light position and initial model position
Light((0, 5, 0))
#create shaders
shader = Shader("shaders/uv_reflect")
flatsh = Shader("shaders/uv_flat")
defocus = Defocus()

#Create textures
shapeimg = Texture("textures/straw1.jpg")
shapebump = Texture("textures/floor_nm.jpg", True)
shapeshine = Texture("textures/pong3.png")

#Create shape
Ejemplo n.º 38
0
  tank_turret.rotateToZ(roll)
  tank_turret.draw()
  tank_gun.position(x, y, z)
  # adjust gunangle for tilted plane as turret rotates
  tank_gun.rotateToX(pitch + math.cos(math.radians(turret - 180)) * gunangle)
  tank_gun.rotateToY(turret-90)
  tank_gun.rotateToZ(roll - math.sin(math.radians(turret - 180)) * gunangle)
  tank_gun.draw()


# Update display before we begin (user might have moved window)
win.update()
DISPLAY.resize(win.winx, win.winy, win.width, win.height - bord)

is_running = True
CAMERA = Camera.instance()

try:
  while DISPLAY.loop_running():
    mx, my = mymouse.position()
    mouserot -= (mx-omx)*0.2
    tilt += (my-omy)*0.2
    omx=mx
    omy=my

    CAMERA.reset()
    dot1.set_2d_location(DISPLAY.width - 105.0 + 200.0*xm/mapwidth,
                        DISPLAY.height - 105.0 - 200.0*zm/mapdepth)
    dot2.set_2d_location(DISPLAY.width - 105.0 + 200.0*etx/mapwidth,
                        DISPLAY.height - 105.0 - 200.0*etz/mapdepth)
    dot1.draw()
Ejemplo n.º 39
0
class StereoCam(object):
  """For creating an apparatus with two sprites to hold left and right
  eye views.

  This Class is used to hold the 3D Camera which should be used to draw
  the 3D objects. It also holds a 2D Camera for drawing the Sprites"""
  def __init__(self, shader="uv_flat", mipmap=False, separation=0.4):
    """ 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

      *separation*
        distance between the two camera positions - how wide apart the
        eye views are.
    """
    # load shader
    self.shader = Shader(shader)
    self.camera_3d = Camera()
    self.camera_2d = Camera(is_3d=False)
    self.offs = separation / 2.0
    self.textures = []
    self.sprites = []
    self.tex_list = []
    for i in range(2):
      self.textures.append(OffScreenTexture(name="bin"))
      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, x=-ix/2.0 + i*ix, w=ix, h=iy, flip=True))
      self.sprites[i].set_offset((i * 0.5 - 0.25, 0.0))
      self.textures[i].alpha = False
      self.textures[i].blend = True
      self.textures[i].mipmap = mipmap
      self.tex_list.append([self.textures[i]])

  def move_camera(self, position, rot, tilt):
    self.camera_3d.reset()
    self.camera_3d.rotate(tilt, rot, 0)
    self.camera_3d.position(position)

  def start_capture(self, side):
    """ after calling this method all object.draw()s will rendered
    to this texture and not appear on the display.

      *side*
        Either 0 or 1 to determine stereoscopic view
    """
    offs = -self.offs if side == 0 else self.offs
    self.camera_3d.position((self.camera_3d.mtrx[2,3] * offs, 0,
                            -self.camera_3d.mtrx[0,3] * offs))
    tex = self.textures[side]
    tex._start()
    xx = tex.ix / 4.0 # draw the middle only - half width
    yy = 0
    ww = tex.ix / 2.0
    hh = tex.iy
    opengles.glEnable(GL_SCISSOR_TEST)
    opengles.glScissor(ctypes.c_int(int(xx)), ctypes.c_int(int(yy)),
                  ctypes.c_int(int(ww)), ctypes.c_int(int(hh)))

  def end_capture(self, side):
    """ stop capturing to texture and resume normal rendering to default
    """
    self.textures[side]._end()
    opengles.glDisable(GL_SCISSOR_TEST)

  def draw(self):
    """ draw the shape using the saved texture
    """
    for i in range(2):
     self.sprites[i].draw(self.shader, self.tex_list[i], 0.0, 0.0, self.camera_2d)
Ejemplo n.º 40
0
from pi3d.shape.Sphere import Sphere

from pi3d.util.String import String
from pi3d.util.Screenshot import screenshot
from pi3d.util.Defocus import Defocus

#helpful messages
print("############################################################")
print("Mouse to move left and right and up and down")
print("############################################################")
print()

# Setup display and initialise pi3d
DISPLAY = Display.create(x=200, y=200, frames_per_second=20)
DISPLAY.set_background(0.4, 0.8, 0.8, 1)  # r,g,b,alpha
camera = Camera((0, 0, 0), (0, 0, -1),
                (1, 1000, 30.0, DISPLAY.width / DISPLAY.height))
light = Light((10, -10, 20))
# load shader
shader = Shader("shaders/uv_reflect")
flatsh = Shader("shaders/uv_flat")
defocus = Defocus()
#========================================

# Setting 2nd param to True renders 'True' Blending
# (this can be changed later to 'False' with 'rockimg2.blend = False')
groundimg = Texture("textures/stripwood.jpg")
monstimg = Texture("textures/pong3.png")
ballimg = Texture("textures/pong2.jpg")

# environment cube
ectex = Texture("textures/ecubes/skybox_stormydays.jpg")
Ejemplo n.º 41
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)