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 __init__(self): """ calls Texture.__init__ but doesn't need to set file name as texture generated from the framebuffer """ super(Defocus, self).__init__("defocus") # load blur shader self.shader = Shader("defocus")
def __init__(self, camera, shader=None, flip=True, w=None, h=None, z=1): """Camera must be a 2d camera. Extra Keyword arguments: *flip* Should the image be flipped over *w* and *h* default to display size if not defined *center* put the sprite at the full screen center. The main display must be initialized first if using """ from pi3d.Display import Display scrnheight = Display.INSTANCE.height scrnwidth = Display.INSTANCE.width if w==None: width = Display.INSTANCE.width else: width = w if h==None: height = Display.INSTANCE.height else: height = h self.xoffset = int((width - scrnwidth) * 0.5) self.yoffset = int((height - scrnheight) * 0.5) super(Layer, self).__init__("Layer", w, h) self.sprite = FlipSprite(camera=camera, w=self.ix, h=self.iy, z=z, flip=True) # If not defined, load shader for drawing layer if shader==None: self.shader = Shader("uv_flat") else: self.shader = shader
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)
def __init__(self): """ calls Texture.__init__ but doesn't need to set file name as texture generated from the framebuffer """ super(Clashtest, self).__init__("clashtest") # load clashtest shader self.shader = Shader("clashtest") self.img = np.zeros((self.ix, 4), dtype=np.uint8) self.step = int(self.ix / 100) self.s_flg = False self.y0 = int(self.iy / 2)
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("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.058 # used to hold "patch size" passed to shader #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]
def __init__(self): """ calls Texture.__init__ but doesn't need to set file name as texture generated from the framebuffer """ super(Clashtest, self).__init__("clashtest") # load clashtest shader self.shader = Shader("clashtest") self.img = (ctypes.c_char * (self.ix * 3))() self.step = 3 * int(self.ix / 50) self.img_sz = len(self.img)-3 self.s_flg = False self.y0 = int(self.iy / 2)
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 __init__(self): """ calls Texture.__init__ but doesn't need to set file name as texture generated from the framebuffer """ super(Defocus, self).__init__("defocus") 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 blur shader self.shader = Shader("shaders/defocus")
def draw(self, shape=None, M=None, unif=None, shader=None, textures=None, ntl=None, shny=None, fullset=True): """Draw this Buffer, called by the parent Shape.draw() Keyword arguments: *shape* Shape object this Buffer belongs to, has to be passed at draw to avoid circular reference *shader* Shader object *textures* array of Texture objects *ntl* multiple for tiling normal map which can be less than or greater than 1.0. 0.0 disables the normal mapping, float *shiny* how strong to make the reflection 0.0 to 1.0, float """ self.load_opengl() shader = shader or self.shader or shape.shader or Shader.instance() shader.use() opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, GLsizei(3), GLboolean(0), M.ctypes.data) opengles.glUniform3fv(shader.unif_unif, GLsizei(20), unif) textures = textures or self.textures if ntl is not None: self.unib[0] = ntl if shny is not None: self.unib[1] = shny self._select() opengles.glVertexAttribPointer(shader.attr_vertex, GLint(3), GL_FLOAT, GLboolean(0), self.N_BYTES, 0) opengles.glEnableVertexAttribArray(shader.attr_vertex) if self.N_BYTES > 12: opengles.glVertexAttribPointer(shader.attr_normal, GLint(3), GL_FLOAT, GLboolean(0), self.N_BYTES, 12) opengles.glEnableVertexAttribArray(shader.attr_normal) if self.N_BYTES > 24: opengles.glVertexAttribPointer(shader.attr_texcoord, GLint(2), GL_FLOAT, GLboolean(0), self.N_BYTES, 24) opengles.glEnableVertexAttribArray(shader.attr_texcoord) opengles.glDisable(GL_BLEND) self.unib[2] = 0.6 for t, texture in enumerate(textures): if (self.disp.last_textures[t] != texture or self.disp.last_shader != shader or self.disp.offscreen_tex): # very slight speed increase for sprites opengles.glActiveTexture(GL_TEXTURE0 + t) assert texture.tex(), 'There was an empty texture in your Buffer.' opengles.glBindTexture(GL_TEXTURE_2D, texture.tex()) opengles.glUniform1i(shader.unif_tex[t], GLint(t)) self.disp.last_textures[t] = texture if texture.blend: # i.e. if any of the textures set to blend then all will for this shader. self.unib[2] = 0.05 if self.unib[2] != 0.6 or shape.unif[13] < 1.0 or shape.unif[14] < 1.0: #use unib[2] as flag to indicate if any Textures to be blended #needs to be done outside for..textures so materials can be transparent opengles.glEnable(GL_BLEND) self.unib[2] = 0.05 self.disp.last_shader = shader opengles.glUniform3fv(shader.unif_unib, GLsizei(5), self.unib) opengles.glEnable(GL_DEPTH_TEST) # TODO find somewhere more efficient to do this opengles.glDrawElements(self.draw_method, GLsizei(self.ntris * 3), GL_UNSIGNED_SHORT, 0)
from pi3d.Light import Light rads = 0.017453292512 # degrees to radians #Create a Tkinter window in Display winw,winh = 200, 600 #64MB GPU memory setting #winw,winh = 1920,1180 #128MB GPU memory setting DISPLAY = Display.create(tk=True, window_title='ConferenceHall demo in Pi3D', w=winw, h=winh, far=2200.0, fov = 60, background=(0.4, 0.8, 0.8, 1), frames_per_second=20) win = DISPLAY.tkwin #Setup shaders flatsh = Shader("shaders/uv_flat") shade2d = Shader('shaders/2d_flat') # create splash screen and draw it splash = ImageSprite("textures/pi3d_splash.jpg", shade2d, w=10, h=10, z=0.2) splash.draw() DISPLAY.swap_buffers() #Setup environment cube ectex = EnvironmentCube.loadECfiles("textures/ecubes/Miramar", "miramar_256", "png", nobottom = True) myecube = EnvironmentCube.EnvironmentCube(size=1800.0, maptype="FACES", nobottom=True) myecube.set_draw_details(flatsh,ectex) #Load Hall model hall = Model(file_string="models/ConferenceHall/conferencehall.egg", name="Hall", sx=0.1, sy=0.1, sz=0.1) hall.set_shader(flatsh)
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('mat_pointsprite') self.set_shader(shader) self.buf[0].unib[0] = hardness else: self.lite = False shader = Shader('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
from pi3d.Keyboard import Keyboard from pi3d.Mouse import Mouse from pi3d.Texture import Texture from pi3d.Camera import Camera from pi3d.Shader import Shader from pi3d.shape.EnvironmentCube import EnvironmentCube from pi3d.shape.EnvironmentCube import loadECfiles from pi3d.util.Screenshot import screenshot from pi3d.util import Utility # Setup display and initialise pi3d DISPLAY = Display.create(x=50, y=50) shader = Shader('shaders/uv_flat') #======================================== #select the environment cube with 'box'... box = 3 if box == 0: ectex = [Texture('textures/ecubes/skybox_interstellar.jpg')] myecube = EnvironmentCube(size=900.0, maptype='CROSS') elif box == 1: ectex = [Texture('textures/ecubes/SkyBox.jpg')] myecube = EnvironmentCube(size=900.0, maptype='HALFCROSS') elif box == 2: ectex = loadECfiles('textures/ecubes', 'sbox_interstellar', nobottom=True) myecube = EnvironmentCube(size=900.0, maptype='FACES', nobottom=True) else: ectex = loadECfiles('textures/ecubes', 'skybox_hall')
def draw(self, shape=None, M=None, unif=None, shader=None, textures=None, ntl=None, shny=None, fullset=True): """Draw this Buffer, called by the parent Shape.draw() Keyword arguments: *shape* Shape object this Buffer belongs to, has to be passed at draw to avoid circular reference *shader* Shader object *textures* array of Texture objects *ntl* multiple for tiling normal map which can be less than or greater than 1.0. 0.0 disables the normal mapping, float *shiny* how strong to make the reflection 0.0 to 1.0, float """ self.load_opengl() shader = shader or self.shader or shape.shader or Shader.instance() shader.use() opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 3, ctypes.c_int(0), M.ctypes.data) opengles.glUniform3fv(shader.unif_unif, 20, ctypes.byref(unif)) textures = textures or self.textures if ntl is not None: self.unib[0] = ntl if shny is not None: self.unib[1] = shny self._select() opengles.glVertexAttribPointer(shader.attr_vertex, 3, GL_FLOAT, 0, self.N_BYTES, 0) opengles.glEnableVertexAttribArray(shader.attr_vertex) if self.N_BYTES > 12: opengles.glVertexAttribPointer(shader.attr_normal, 3, GL_FLOAT, 0, self.N_BYTES, 12) opengles.glEnableVertexAttribArray(shader.attr_normal) if self.N_BYTES > 24: opengles.glVertexAttribPointer(shader.attr_texcoord, 2, GL_FLOAT, 0, self.N_BYTES, 24) opengles.glEnableVertexAttribArray(shader.attr_texcoord) opengles.glDisable(GL_BLEND) self.unib[2] = 0.6 for t, texture in enumerate(textures): if (self.disp.last_textures[t] != texture or self.disp.last_shader != shader): # very slight speed increase for sprites opengles.glActiveTexture(GL_TEXTURE0 + t) assert texture.tex(), 'There was an empty texture in your Buffer.' opengles.glBindTexture(GL_TEXTURE_2D, texture.tex()) opengles.glUniform1i(shader.unif_tex[t], t) self.disp.last_textures[t] = texture if texture.blend: # i.e. if any of the textures set to blend then all will for this shader. self.unib[2] = 0.05 if self.unib[2] != 0.6 or shape.unif[5,2] < 1.0 or shape.unif[5,1] < 1.0: #use unib[2] as flag to indicate if any Textures to be blended #needs to be done outside for..textures so materials can be transparent opengles.glEnable(GL_BLEND) self.unib[2] = 0.05 self.disp.last_shader = shader opengles.glUniform3fv(shader.unif_unib, 4, ctypes.byref(self.unib)) opengles.glEnable(GL_DEPTH_TEST) # TODO find somewhere more efficient to do this opengles.glDrawElements(self.draw_method, self.ntris * 3, GL_UNSIGNED_SHORT, 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 from pi3d.Shader import Shader camera = camera or self._camera or Camera.instance() shader = shader or self.shader or Shader.instance() shader.use() if self.MFlg or len(mlist) > 0: ''' # 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.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) # 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 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 camera.was_moved: self.unif[18:21] = camera.eye[0:3] opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2, ctypes.c_int(0), self.M.ctypes.data) 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)
# Create a Tkinter window winw, winh, bord = 1200, 600, 0 #64MB GPU memory setting # winw,winh,bord = 1920,1200,0 #128MB GPU memory setting DISPLAY = Display.create(tk=True, window_title='Tiger Tank demo in Pi3D', w=winw, h=winh - bord, far=2200.0, background=(0.4, 0.8, 0.8, 1), frames_per_second=16) #inputs = InputEvents() #inputs.get_mouse_movement() Light(lightpos=(-1, -1, 1), lightcol =(0.8, 0.8, 0.8), lightamb=(0.30, 0.30, 0.32)) win = DISPLAY.tkwin shader = Shader('shaders/uv_reflect') flatsh = Shader('shaders/uv_flat') shade2d = Shader('shaders/2d_flat') #======================================== # create splash screen and draw it splash = ImageSprite("textures/tiger_splash.jpg", shade2d, w=10, h=10, z=0.2) splash.draw() DISPLAY.swap_buffers() # create environment cube ectex = EnvironmentCube.loadECfiles('textures/ecubes/Miramar', 'miramar_256', suffix='png') myecube = EnvironmentCube.EnvironmentCube(size=1800.0, maptype='FACES') myecube.set_draw_details(flatsh, ectex)
from pi3d import Display from pi3d.Keyboard import Keyboard from pi3d.Texture import Texture from pi3d.Shader import Shader from pi3d.Light import Light from pi3d.shape.Model import Model from pi3d.util.Screenshot import screenshot # Setup display and initialise pi3d DISPLAY = Display.create(x=100, y=100, background=(0.2, 0.4, 0.6, 1)) Light((1, 1, 1)) shader = Shader("shaders/mat_reflect") #======================================== # load bump and reflection textures bumptex = Texture("textures/floor_nm.jpg") shinetex = Texture("textures/stars.jpg") # load model_loadmodel mymodel = Model(file_string='models/teapot.egg', name='teapot', x=0, y=0, z=10) mymodel.set_shader(shader) # material is set in the file mymodel.set_normal_shine(bumptex, 4.0, shinetex, 0.2, is_uv = False) # Fetch key presses mykeys = Keyboard() while DISPLAY.loop_running():
print("N.B. W now works as a TOGGLE one press to go one to stop.") print("At the edge you will turn into a ghost and be able to fly ") print("and pass through rocks! There are limited numbers of jumps.") print("Good turnings are often greener and tend to be near") print("(but in the opposite direction to) big holes") print("############################################################") print("If you get touched by a monster you will return to the start!") print("############################################################") print() # Setup display and initialise pi3d DISPLAY = Display.create(x=100, y=100, background=(0.4, 0.8, 0.8, 1)) shader = Shader("shaders/uv_reflect") flatsh = Shader("shaders/uv_flat") #======================================== # load Textures rockimg1 = Texture("textures/techy1.jpg") rockimg2 = Texture("textures/rocktile2.jpg") tree2img = Texture("textures/tree2.png") raspimg = Texture("textures/Raspi256x256.png") monstimg = Texture("textures/pong2.jpg") monsttex = Texture("textures/floor_nm.jpg") shineimg = Texture("textures/stars.jpg") # environment cube ectex = Texture("textures/ecubes/skybox_stormydays.jpg") myecube = EnvironmentCube(size=900.0, maptype="CROSS")
from pi3d import Display from pi3d.Keyboard import Keyboard from pi3d.Shader import Shader from pi3d.shape.Model import Model from pi3d.util.Screenshot import screenshot # Setup display and initialise pi3d DISPLAY = Display.create(x=50, y=50, w=-100, h=-100, background=(0.2, 0.4, 0.6, 1)) shader = Shader('shaders/uv_light') #======================================== # load model_loadmodel mymodel = Model(file_string='models/Triceratops/Triceratops.egg', name='Triceratops', x=0, y=-1, z=40, sx=0.005, sy=0.005, sz=0.005) mymodel.set_shader(shader) # Fetch key presses mykeys = Keyboard()
def __init__(self, camera=None, light=None, w=1.0, h=1.0, corner=0.1, name="", texture=None, shader=None, x=0.0, y=0.0, z=20.0, rx=0.0, ry=0.0, rz=0.0, sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0): """Uses standard constructor for Shape. Extra Keyword arguments: *w* Width. *h* Height. *corner* The size that the edge thirds will be. Used for mapping textures to plane """ super(ButtonSprite, self).__init__(camera, light, name, x, y, z, rx, ry, rz, sx, sy, sz, cx, cy, cz) self.width = w self.height = h self.corner = corner verts = [] norms = [] texcoords = [] inds = [] ww = w / 2.0 hh = h / 2.0 for (j, y) in enumerate((hh, hh - corner, -hh + corner, -hh)): y_uv = j / 3.0 for (i, x) in enumerate((-ww, -ww + corner, ww - corner, ww)): x_uv = i / 3.0 verts.extend([[x, y, 0.0]]) norms.extend([[0.0, 0.0, -1.0]]) texcoords.extend([[x_uv, y_uv]]) if i > 0 and j > 0: n = j * 4 + i inds.extend([[n - 1, n - 5, n - 4], [n - 4, n, n - 1]]) self.buf = [Buffer(self, verts, texcoords, inds, norms)] if texture is None: for p in sys.path: img_path = os.path.join(p, "pi3d/shape/button_image.png") if os.path.exists(img_path): texture = Texture(img_path) break else: if not isinstance(texture, Texture): # i.e. can load from file name texture = Texture(texture) if shader is None: shader = Shader("uv_flat") else: if not isinstance(shader, Shader): shader = Shader(shader) self.set_draw_details(shader, [texture])
from pi3d.Camera import Camera from pi3d.Shader import Shader from pi3d.shape.EnvironmentCube import EnvironmentCube from pi3d.shape.EnvironmentCube import loadECfiles from pi3d.shape.Model import Model from pi3d.util.Screenshot import screenshot # Setup display and initialise pi3d DISPLAY = Display.create(x=100, y=100) DISPLAY.set_background(1.0,0.4,0.6,1) # r,g,b,alpha Light((5, -10, -20), (0.6, 0.6, 0.5), (0.3, 0.3, 0.4)) # load shader shader = Shader("shaders/uv_light") flatsh = Shader("shaders/uv_flat") print("==============================================================") print("Instructions:") print("") print("Keys- W - Forward,") print(" A - Left S - Back D - right") print("") print("Move mouse to pan view. Click mouse to exit or press ESCAPE") print("==============================================================") ectex = loadECfiles("textures/ecubes","sbox") myecube = EnvironmentCube(size=900.0, maptype="FACES", name="bfa", y=50.0) myecube.set_draw_details(flatsh, ectex)
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 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 from pi3d.Shader import Shader camera = camera or self._camera or Camera.instance() shader = shader or self.shader or Shader.instance() shader.use() if self.MFlg 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))))) ''' 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) 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 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 camera.was_moved: self.unif[18:21] = camera.eye[0:3] opengles.glUniformMatrix4fv(shader.unif_modelviewmatrix, 2, ctypes.c_int(0), self.M.ctypes.data) 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)
speed = 1 widex = 100 widey = 80 cloudno = 20 cloud_depth = 350.0 zd = 1.0 * cloud_depth / cloudno MARGIN = 100 # Setup display and initialise pi3d DISPLAY = Display.create(x=MARGIN, y=MARGIN) scnx = DISPLAY.width scny = DISPLAY.height DISPLAY.set_background(0, 0.7, 1, 1) shader = Shader("shaders/uv_flat") ############################# cloudTex = [] cloudTex.append(Texture("textures/cloud2.png", True)) cloudTex.append(Texture("textures/cloud3.png", True)) cloudTex.append(Texture("textures/cloud4.png", True)) cloudTex.append(Texture("textures/cloud5.png", True)) cloudTex.append(Texture("textures/cloud6.png", True)) # Setup cloud positions and cloud image refs cz = 0.0 clouds = [] # an array for the clouds for b in range(0, cloudno): size = 0.5 + random.random() / 2.0 cloud = Sprite(w=size * widex,
def __init__(self, pex_file, emission_rate=10, scale=1.0, rot_rate=None, rot_var=0.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: 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.scale = scale self.rot_rate = rot_rate self.rot_var = rot_var ''' make the numpy arrays to hold the particle info vertices[0] x position of centre of point relative to centre of screen in pixels vertices[1] y position vertices[2] z depth but fract(z) is used as a multiplier for point size normals[0] rotation in radians normals[1] red and green values to multiply with the texture 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 tex_coords[0] distance of left side of sprite square from left side of texture in uv scale 0.0 to 1.0 tex_coords[1] distance of top of sprite square from top of texture arr[8] x velocity arr[9] y velocity arr[10] lifespan arr[11] lifespan remaining arr[12:16] rgba target values arr[16:20] rgba difference arr[20] size delta (finish size - start size) / full_lifespan arr[21] radial acceleration arr[22] tangential acceleration ''' self.arr = np.zeros((self.maxParticles, 23), dtype='float32') self.point_size = max(self.startParticleSize + self.startParticleSizeVariance, self.finishParticleSize + self.FinishParticleSizeVariance) #NB capital F! super(PexParticles, self).__init__(vertices=self.arr[:,0:3], normals=self.arr[:,3:6], tex_coords=self.arr[:,6:8], point_size=self.point_size * self.scale, **kwargs) # pass to Points.__init__() shader = Shader('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
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)