def load_texture(path): import pygame #Cargo la imagen a memoria. pygame se hace cargo de decodificarla correctamente surf = pygame.image.load(path) surf = pygame.transform.flip(surf, False, True) #Obtengo la matriz de colores de la imagen en forma de un array binario #Le indico el formato en que quiero almacenar los datos (RGBA) y que invierta la matriz, para poder usarla correctamente con OpenGL image = pygame.image.tostring(surf, 'RGBA', 1) #Obentego las dimensiones de la imagen ix, iy = surf.get_rect().size #Creo una textura vacia en memoria de video, y me quedo con el identificador (texid) para poder referenciarla texid = glGenTextures(1) #Activo esta nueva textura para poder cargarle informacion glBindTexture(GL_TEXTURE_2D, texid) #Seteo los tipos de filtro a usar para agrandar y achivar la textura glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) #Cargo la matriz de colores dentro de la textura #Los parametros que le paso son: # - Tipo de textura, en este caso GL_TEXTURE_2D # - Nivel de mipmap, en este caso 0 porque no estoy usando mas niveles # - Formato en que quiero almacenar los datos en memoria de video, GL_RGB en este caso, porque no necesito canal Alfa # - Ancho de la textura # - Alto de la textura # - Grosor en pixels del borde, en este caso 0 porque no quiero agregar borde a al imagen # - Formato de los datos de la imagen, en este caso GL_RGBA que es como lo leimos con pygame.image # - Formato de los canales de color, GL_UNSIGNED_BYTE quiere decir que son 8bits para cada canal # - La imagen, en este caso la matriz de colores que creamos con pygame.image.tostring glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) #Una vez que tengo todo cargado, desactivo la textura para evitar que se dibuje por error mas adelante #Cada vez que quiera usarla, puedo hacer glBindTexture con el identificador (texid) que me guarde al crearla glBindTexture(GL_TEXTURE_2D, 0) #devuelvo el identificador de la textura para que pueda ser usada mas adelante return texid
def parse_mtl(filename): contents = {} mtl = None for line in open(filename, "r"): if line.startswith('#'): continue values = line.split() if not values: continue if values[0] == 'newmtl': mtl = contents[values[1]] = {} elif mtl is None: raise ValueError("mtl file doesn't start with newmtl stmt") elif values[0] == 'map_Kd': # load the texture referred to by this declaration mtl[values[0]] = values[1] surf_file = mtl['map_Kd'] if surf_file.endswith('.tga'): TGA_Header surf = pygame.image.load() image = pygame.image.tostring(surf, 'RGBA', 1) ix, iy = surf.get_rect().size texid = mtl['texture_Kd'] = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texid) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) else: mtl[values[0]] = list(map(float, values[1:])) return contents
def update_texture_rgb24(self, img_data, x, y, width, height, rowstride): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride / 3) if self.current_mode == GLClientWindow.MODE_YUV: raise Exception("** YUV -> RGB mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new RGB texture") w, h = self.get_size() # First time we draw must be full image assert w == width and h == height glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0) self.current_mode = GLClientWindow.MODE_RGB log("Updating RGB texture") glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data) drawable.gl_end() self.render_image()
def __init__(self, face: freetype.Face, char: str) -> None: if face.load_char(char, freetype.FT_LOAD_RENDER): raise RuntimeError('failed to load char \'%s\'' % char) glyph = face.glyph bitmap = glyph.bitmap assert bitmap.pixel_mode == freetype.FT_PIXEL_MODE_GRAY, \ "We haven't implemented support for other pixel modes" glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT) glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) self._texture_id = glGenTextures(1) self._width = bitmap.width self._height = bitmap.rows self._descender = glyph.bitmap_top - self._height self._bearing_x = glyph.bitmap_left self._advance = numpy.array( [face.glyph.advance.x / 64.0, face.glyph.advance.y / 64.0]) glBindTexture(GL_TEXTURE_2D, self._texture_id) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) data = numpy.array(bitmap.buffer, numpy.ubyte).reshape(self._height, self._width) glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, self._width, self._height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, numpy.flipud(data)) glPopClientAttrib()
def set_texture_level(): #only really needed with some drivers (NVidia) #may cause errors with older drivers: try: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) except: pass
def set_texture_level(target=GL_TEXTURE_RECTANGLE_ARB): #only really needed with some drivers (NVidia) #may cause errors with older drivers: try: glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) except: pass
def update_texture_rgb24(self, img_data, x, y, width, height, rowstride): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride/3) if self.current_mode == GLClientWindow.MODE_YUV: raise Exception("** YUV -> RGB mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new RGB texture") w, h = self.get_size() # First time we draw must be full image assert w == width and h == height glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0) self.current_mode = GLClientWindow.MODE_RGB log("Updating RGB texture") glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data) drawable.gl_end() self.render_image()
def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x+w>ww or y+h>wh: log("do_paint_rgb24: ignoring paint which would overflow the backing area") return drawable = self.gl_init() if not drawable: log("do_paint_rgb24: cannot paint yet..") return try: #cleanup if we were doing yuv previously: if self.pixel_format!=GLPixmapBacking.RGB24: self.remove_shader() self.pixel_format = GLPixmapBacking.RGB24 glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride/3) for texture in (GL_TEXTURE1, GL_TEXTURE2): glActiveTexture(texture) glDisable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, img_data) glBegin(GL_QUADS) for rx,ry in ((x, y), (x, y+h), (x+w, y+h), (x+w, y)): glTexCoord2i(rx, ry) glVertex2i(rx, ry) glEnd() finally: self.gl_end(drawable)
def set_texture_level(): #only really needed with some drivers (NVidia) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) #may cause errors with older drivers: try: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) except: pass
def gl_init(self): drawable = self.gl_begin() w, h = self.size debug("%s.gl_init() GL Pixmap backing size: %d x %d, drawable=%s", self, w, h, drawable) if not drawable: return None if not self.debug_setup: self.debug_setup = True self.gl_init_debug() if not self.gl_setup: self.gl_marker("Initializing GL context for window size %d x %d" % (w, h)) # Initialize viewport and matrices for 2D rendering glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) # Could be more optimal to use vertex arrays: # glEnableClientState(GL_VERTEX_ARRAY) # glEnableClientState(GL_TEXTURE_COORD_ARRAY) # Clear background to transparent black glClearColor(0.0, 0.0, 0.0, 0.0) # Default state is good for YUV painting: # - fragment program enabled # - YUV fragment program bound # - render to offscreen FBO if self.textures is None: self.gl_init_textures() # Define empty FBO texture and set rendering to FBO glEnable(GL_FRAGMENT_PROGRAM_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) # nvidia needs this even though we don't use mipmaps (repeated through this file): glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, w, h, 0, self.texture_pixel_format, GL_UNSIGNED_BYTE, None) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glClear(GL_COLOR_BUFFER_BIT) # Create and assign fragment programs if not self.shaders: self.gl_init_shaders() # Bind program 0 for YUV painting by default glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[YUV2RGB_SHADER]) self.gl_setup = True return drawable
def __init__(self): self._texId = glGenTextures(1) self._width = None self._height = None # Bind an ID for this texture glBindTexture(GL_TEXTURE_2D, self._texId) # Use bilinear filtering if the texture has to be scaled glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
def gl_init(self): drawable = self.gl_begin() w, h = self.size log("%s.gl_init() GL Pixmap backing size: %d x %d, drawable=%s", self, w, h, drawable) if not drawable: return None if not self.debug_setup: self.debug_setup = True self.gl_init_debug() if not self.gl_setup: self.gl_marker("Initializing GL context for window size %d x %d" % (w, h)) # Initialize viewport and matrices for 2D rendering glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) # Could be more optimal to use vertex arrays: # glEnableClientState(GL_VERTEX_ARRAY) # glEnableClientState(GL_TEXTURE_COORD_ARRAY) # Clear background to transparent black glClearColor(0.0, 0.0, 0.0, 0.0) # we don't use the depth (2D only): glDisable(GL_DEPTH_TEST) # only do alpha blending in present_fbo: glDisable(GL_BLEND) # Default state is good for YUV painting: # - fragment program enabled # - YUV fragment program bound # - render to offscreen FBO if self.textures is None: self.gl_init_textures() # Define empty FBO texture and set rendering to FBO glEnable(GL_FRAGMENT_PROGRAM_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) # nvidia needs this even though we don't use mipmaps (repeated through this file): glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, w, h, 0, self.texture_pixel_format, GL_UNSIGNED_BYTE, None) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glClear(GL_COLOR_BUFFER_BIT) # Create and assign fragment programs if not self.shaders: self.gl_init_shaders() # Bind program 0 for YUV painting by default glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[YUV2RGB_SHADER]) self.gl_setup = True return drawable
def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options, callbacks): debug("_do_paint_rgb24(x=%d, y=%d, width=%d, height=%d rowstride=%d)", x, y, width, height, rowstride) drawable = self.gl_init() if not drawable: debug("OpenGL cannot paint rgb24, drawable is not set") return False self.set_rgb24_paint_state() # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a - 1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * 3) > a: row_length = width + (rowstride - width * 3) / 3 self.gl_marker( "Painting RGB24 update at %d,%d, size %d,%d, stride is %d, row length %d, alignment %d" % (x, y, width, height, rowstride, row_length, alignment)) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y + height) glTexCoord2i(width, height) glVertex2i(x + width, y + height) glTexCoord2i(width, 0) glVertex2i(x + width, y) glEnd() # Present update to screen self.present_fbo() # present_fbo has resetted state already drawable.gl_end() return True
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): assert x==0 and y==0 assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) divs = get_subsampling_divs(pixel_format) debug("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) self.gl_marker("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div_w > 1 or div_h > 1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/div_w, height/div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) debug("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [ 1 ] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) self.gl_marker("Updating YUV textures") divs = get_subsampling_divs(pixel_format) U_width = 0 U_height = 0 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) if index == 1: U_width = width/div_w U_height = height/div_h elif index == 2: if width/div_w != U_width: log.error("Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width/div_w, U_width, pixel_format) if height/div_h != U_height: log.error("Height of V plane is %d, differs from height of corresponding U plane (%d)", height/div_h, U_height)
def gl_init(self): #must be called within a context! #performs init if needed if not self.debug_setup: self.debug_setup = True self.gl_init_debug() if not self.gl_setup: w, h = self.size self.gl_marker("Initializing GL context for window size %d x %d", w, h) # Initialize viewport and matrices for 2D rendering glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) # Mesa docs claim: this hint can improve the speed of texturing #when perspective-correct texture coordinate interpolation isn't needed, #such as when using a glOrtho() projection: glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST) # Could be more optimal to use vertex arrays: # glEnableClientState(GL_VERTEX_ARRAY) # glEnableClientState(GL_TEXTURE_COORD_ARRAY) # Clear background to transparent black glClearColor(0.0, 0.0, 0.0, 0.0) # we don't use the depth (2D only): glDisable(GL_DEPTH_TEST) # only do alpha blending in present_fbo: glDisable(GL_BLEND) # Default state is good for YUV painting: # - fragment program enabled # - YUV fragment program bound # - render to offscreen FBO if self.textures is None: self.gl_init_textures() # Define empty FBO texture and set rendering to FBO glEnable(GL_FRAGMENT_PROGRAM_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) # nvidia needs this even though we don't use mipmaps (repeated through this file): glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, w, h, 0, self.texture_pixel_format, GL_UNSIGNED_BYTE, None) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glClear(GL_COLOR_BUFFER_BIT) # Create and assign fragment programs if not self.shaders: self.gl_init_shaders() # Bind program 0 for YUV painting by default glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[YUV2RGB_SHADER]) self.gl_setup = True
def main(path=None): glutInit(sys.argv) if sys.platform == 'darwin': if not path: path = dialog() if not path: sys.exit(0) glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE) glutInitWindowPosition(0, 0) glutInitWindowSize(730, 650) win = glutCreateWindow(b'MIDI Player') (width, height, img) = read_image(join(dirname(__file__), 'mixer.ppm')) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glMatrixMode(GL_TEXTURE) glLoadIdentity() glScale(1 / width, 1 / height, 1) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, 730, 0, 650, 0, 1) player = Player(win, path, width, height) glutDisplayFunc(player.display_func) glutKeyboardFunc(player.keyboard_func) glutMouseFunc(player.mouse_func) glutMotionFunc(player.motion_func) glutIdleFunc(player.process_events) submenus = [] for instrument in range(128): if instrument % 8 == 0: submenus.append([ families[instrument // 8], glutCreateMenu(player.change_instrument) ]) glutAddMenuEntry(instruments[instrument].encode('ascii'), instrument) glutCreateMenu(player.change_instrument) for family, submenu in submenus: glutAddSubMenu(family.encode('ascii'), submenu) glutAttachMenu(GLUT_RIGHT_BUTTON) glutMainLoop()
def main(path=None): glutInit(sys.argv) if sys.platform == 'darwin': if not path: path = dialog() if not path: sys.exit(0) glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE) glutInitWindowPosition(0, 0) glutInitWindowSize(730, 650) win = glutCreateWindow(b'MIDI Player') (width, height, img) = read_image(join(dirname(__file__), 'mixer.ppm')) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glMatrixMode(GL_TEXTURE) glLoadIdentity() glScale(1/width, 1/height, 1) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0, 730, 0, 650, 0, 1) player = Player(win, path, width, height) glutDisplayFunc(player.display_func) glutKeyboardFunc(player.keyboard_func) glutMouseFunc(player.mouse_func) glutMotionFunc(player.motion_func) glutIdleFunc(player.process_events) submenus = [] for instrument in range(128): if instrument % 8 == 0: submenus.append([families[instrument // 8], glutCreateMenu(player.change_instrument)]) glutAddMenuEntry(instruments[instrument].encode('ascii'), instrument) glutCreateMenu(player.change_instrument) for family, submenu in submenus: glutAddSubMenu(family.encode('ascii'), submenu) glutAttachMenu(GLUT_RIGHT_BUTTON) glutMainLoop()
def make_texture( filename=None, image=None, interpolate=True, alpha=False, integer=False, maxlod=None): if image == None: image = pygame.image.load(filename) pixels = pygame.image.tostring(image, "RGBA" if alpha else "RGB", True) texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST if interpolate else GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) if maxlod is not None: glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, maxlod) if alpha: if integer: targetformat = GL_RGBA8UI sourceformat = GL_RGBA_INTEGER else: targetformat = GL_RGBA8 sourceformat = GL_RGBA else: if integer: targetformat = GL_RGB8UI sourceformat = GL_RGB_INTEGER else: targetformat = GL_RGB8 sourceformat = GL_RGB glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE) glTexImage2D( GL_TEXTURE_2D, 0, targetformat, image.get_width(), image.get_height(), 0, sourceformat, GL_UNSIGNED_BYTE, pixels) print glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT) return texture
def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format): window_width, window_height = self.size assert self.textures is not None, "no OpenGL textures!" if self.pixel_format is None or self.pixel_format!=pixel_format: self.pixel_format = pixel_format divs = self.get_subsampling_divs(pixel_format) log("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if div>1: mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/div, window_height/div, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0) log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv_shader: self.yuv_shader = [ 1 ] glGenProgramsARB(1, self.yuv_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv_shader[0]) # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y divs = self.get_subsampling_divs(pixel_format) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): div = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div, height/div, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index]) glFlush()
def LoadTexture(path): # запросим у OpenGL свободный индекс текстуры texture = glGenTextures(1) # сделаем текстуру активной glBindTexture(GL_TEXTURE_2D, texture) # загружаем изображение-текстуру image = Image.open(path) image = image.transpose(Image.FLIP_TOP_BOTTOM) img_data = image.convert("RGBA").tobytes() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data) glGenerateMipmap(GL_TEXTURE_2D) # установим параметры фильтрации текстуры - линейная фильтрация glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # установим параметры "оборачиваниея" текстуры - отсутствие оборачивания glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) #GL_REPEAT glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) #GL_REPEAT # возвращаем текстуру return texture
def drawBackgroundGL(self, painter, rect): painter.beginNativePainting() #This will clear the screen, but also introduce flickering glClearColor(0.0, 1.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); #update the textures of those patches that were updated for t in self._updatableTiles: patch = self.imagePatches[t][self._numLayers] if patch.texture > -1: self._glWidget.deleteTexture(patch.texture) patch.texture = self._glWidget.bindTexture(patch.image) #see 'backingstore' example by Ariya Hidayat glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) #this ensures a seamless transition between tiles glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) self._updatableTiles = [] drawnTiles = 0 for patches in self.imagePatches: patch = patches[self._numLayers] if not patch.rectF.intersect(rect): continue patch.drawTexture() drawnTiles +=1 #print "ImageView2D.drawBackgroundGL: drew %d of %d tiles" % (drawnTiles, len(self.imagePatches)) painter.endNativePainting()
def _setup_texture(self, context_id: str): """Set up the texture for a given context""" gl_texture = self._gl_textures[context_id] = glGenTextures( 1 ) # Create the texture location glBindTexture(GL_TEXTURE_2D, gl_texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) glBindTexture(GL_TEXTURE_2D, gl_texture) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, self._image_width, self._image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, self._image, ) glBindTexture(GL_TEXTURE_2D, 0) log.info("Finished setting up texture atlas in OpenGL")
def makeGLTexture(image_data: np.ndarray, w: int, h: int, repeat=False) -> int: """Loading pygame.Surface as OpenGL texture :return New Texture key""" # getting data from pygame.Surface # bind new texture key = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, key) # SETTING UP glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # настройка сжатия glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) # настройка растяжения if repeat: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexImage2D(GL_TEXTURE_2D, GL_ZERO, GL_RGBA, w, h, GL_ZERO, GL_RGBA, GL_UNSIGNED_BYTE, image_data) # # unbind new texture glBindTexture(GL_TEXTURE_2D, 0) return key
def _createTexture(self): surface = self._textureImage width = surface.get_width() height = surface.get_height() raw = pygame.image.tostring(surface, "RGBA", 0) texture = glGenTextures(1) # glGenTextures fails by returning 0, particularly if there's no GL # context yet. assert texture != 0 glBindTexture(GL_TEXTURE_2D, texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, raw) return texture
def paint_rgb24(self, img_data, x, y, width, height, rowstride): # OpenGL begin if not self.gldrawable.gl_begin(self.glcontext): log.error("OUCH") return False # Upload texture if not self.texture: self.texture = glGenTextures(1) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.texture) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride/3) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data); vtxarrays=1 if vtxarrays == 1: texcoords = [ [ 0, 0 ], [ 0, height], [ width, height], [ width, 0] ] vtxcoords = texcoords glVertexPointeri(vtxcoords) glTexCoordPointeri(texcoords) glDrawArrays(GL_QUADS, 0, 4); else: glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2i(0, 0); glTexCoord2i(0, height); glVertex2i(0, height); glTexCoord2i(width, height); glVertex2i(width, height); glTexCoord2i(width, 0); glVertex2i(width, 0); glEnd() # OpenGL end #self.gldrawable.swap_buffers() # self.gldrawable.swap_buffers() glFinish() self.gldrawable.gl_end()
def paint_rgb24(self, img_data, x, y, width, height, rowstride): # OpenGL begin if not self.gldrawable.gl_begin(self.glcontext): log.error("OUCH") return False # Upload texture if not self.texture: self.texture = glGenTextures(1) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.texture) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride / 3) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data) vtxarrays = 1 if vtxarrays == 1: texcoords = [[0, 0], [0, height], [width, height], [width, 0]] vtxcoords = texcoords glVertexPointeri(vtxcoords) glTexCoordPointeri(texcoords) glDrawArrays(GL_QUADS, 0, 4) else: glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(0, 0) glTexCoord2i(0, height) glVertex2i(0, height) glTexCoord2i(width, height) glVertex2i(width, height) glTexCoord2i(width, 0) glVertex2i(width, 0) glEnd() # OpenGL end #self.gldrawable.swap_buffers() # self.gldrawable.swap_buffers() glFinish() self.gldrawable.gl_end()
def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options, callbacks): debug("_do_paint_rgb24(x=%d, y=%d, width=%d, height=%d rowstride=%d)", x, y, width, height, rowstride) drawable = self.gl_init() if not drawable: debug("OpenGL cannot paint rgb24, drawable is not set") return False self.set_rgb24_paint_state() # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a-1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * 3) > a: row_length = width + (rowstride - width * 3) / 3 self.gl_marker("Painting RGB24 update at %d,%d, size %d,%d, stride is %d, row length %d, alignment %d" % (x, y, width, height, rowstride, row_length, alignment)) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y+height) glTexCoord2i(width, height) glVertex2i(x+width, y+height) glTexCoord2i(width, 0) glVertex2i(x+width, y) glEnd() # Present update to screen self.present_fbo() # present_fbo has resetted state already drawable.gl_end() return True
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s", pixel_format) # Create textures of the same size as the window's empty_buf = b"\0"*(width*height) pixel_data = self.pixels_for_upload(empty_buf)[1] for texture, index in ((GL_TEXTURE0, TEX_Y), (GL_TEXTURE1, TEX_U), (GL_TEXTURE2, TEX_V)): (div_w, div_h) = divs[index] glActiveTexture(texture) target = GL_TEXTURE_RECTANGLE_ARB glBindTexture(target, self.textures[index]) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexImage2D(target, 0, GL_LUMINANCE, width//div_w, height//div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) #glBindTexture(target, 0) #redundant: we rebind below: self.gl_marker("updating planar textures: %sx%s %s", width, height, pixel_format) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 and len(img_data)==3 for texture, index, tex_name in ( (GL_TEXTURE0, TEX_Y, "Y"), (GL_TEXTURE1, TEX_U, "U"), (GL_TEXTURE2, TEX_V, "V"), ): div_w, div_h = divs[index] w = width//div_w h = height//div_h if w==0 or h==0: log.error("Error: zero dimension %ix%i for %s planar texture %s", w, h, pixel_format, tex_name) log.error(" screen update %s dropped", (x, y, width, height)) continue glActiveTexture(texture) target = GL_TEXTURE_RECTANGLE_ARB glBindTexture(target, self.textures[index]) self.set_alignment(w, rowstrides[index], tex_name) upload, pixel_data = self.pixels_for_upload(img_data[index]) log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes, upload=%s", index, divs[index], rowstrides[index], w, h, len(pixel_data), upload) glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0) try: glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0) except: pass glTexSubImage2D(target, 0, 0, 0, w, h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) glBindTexture(target, 0)
def create(self, width, height): self.texture = glGenTextures(1) glBindTexture(GL_TEXTURE_CUBE_MAP, self.texture) for i in range(6): glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE)
def do_paint_rgb(self, rgb_format, img_data, x, y, width, height, rowstride, options, callbacks): log("%s.do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d, options=%s)", self, rgb_format, len(img_data), x, y, width, height, rowstride, options) context = self.gl_context() if not context: log("%s._do_paint_rgb(..) no context!", self) fire_paint_callbacks(callbacks, False, "no opengl context") return if not options.get("paint", True): fire_paint_callbacks(callbacks) return try: upload, img_data = self.pixels_for_upload(img_data) with context: self.gl_init() self.set_rgb_paint_state() #convert it to a GL constant: pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format.decode()) assert pformat is not None, "could not find pixel format for %s" % rgb_format self.gl_marker("%s update at (%d,%d) size %dx%d (%s bytes), using GL %s format=%s", rgb_format, x, y, width, height, len(img_data), upload, CONSTANT_TO_PIXEL_FORMAT.get(pformat)) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) self.set_alignment(width, rowstride, rgb_format) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y+height) glTexCoord2i(width, height) glVertex2i(x+width, y+height) glTexCoord2i(width, 0) glVertex2i(x+width, y) glEnd() self.paint_box(options.get("encoding"), options.get("delta", -1)>=0, x, y, width, height) # Present update to screen self.present_fbo(x, y, width, height, options.get("flush", 0)) # present_fbo has reset state already fire_paint_callbacks(callbacks) except Exception as e: log("Error in %s paint of %i bytes, options=%s)", rgb_format, len(img_data), options) fire_paint_callbacks(callbacks, False, "OpenGL %s paint error: %s" % (rgb_format, e))
def __init__(self, resource_context: ResourceManager, asset_key: str): self._contents = {} current_mtl: dict = None file_data = resource_context.load('assets', asset_key) for line in file_data: line = line.decode("utf-8") # Convert bytes line to a string if line.startswith('#'): # Ignore comments in the file. continue values = line.split() if not values: # Ignore empty lines. continue attribute_name = values[0] if attribute_name == 'newmtl': # Create a new empty material. current_mtl = self._contents[values[1]] = {} elif current_mtl is None: raise ValueError("mtl file must start with newmtl statement") elif attribute_name == 'map_Kd': # Diffuse texture map - load the image into memory. image_name = values[1] image_file_data = resource_context.load('assets', image_name) with Image.open(image_file_data) as image: image_width, image_height = image.size image = image.convert("RGBA").tobytes("raw", "RGBA") # Bind the image as a texture that can be used for rendering. texture_id = glGenTextures(1) current_mtl['texture_Kd'] = texture_id # pylint: disable=unsupported-assignment-operation glBindTexture(GL_TEXTURE_2D, texture_id) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) else: # Store the values for this attribute as a list of float values. current_mtl[attribute_name] = list(map(float, values[1:])) # pylint: disable=unsupported-assignment-operation
def load_texture(path, texture): glBindTexture(GL_TEXTURE_2D, texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) image = Image.open(path) image = image.transpose(Image.FLIP_TOP_BOTTOM) img_data = image.convert("RGBA").tobytes() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data) return texture
def __init__(self, imagefile, points=[], alpha=1.0): super(ImageActor, self).__init__() im = Image.open(imagefile) # Try to open the image file try: ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBA", 0, -1) except SystemError: ix, iy, image = im.size[0], im.size[1], im.tostring("raw", "RGBX", 0, -1) # get a texture buffer glActiveTexture(GL_TEXTURE0) self.texid = glGenTextures(1) # Bind the texture glBindTexture(GL_TEXTURE_2D, self.texid) glPixelStorei(GL_UNPACK_ALIGNMENT,1) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # Upload the image glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image) # Generate the points for the billboard if points == []: points = [Point(0,0), Point(ix,0), Point(ix,-iy), Point(0,-iy)] if len(points) != 4: raise Exception("Image needs 4 points, %d provided" % len(points)) # Generate the UV map uv = [Point(0,1), Point(1,1), Point(1,0), Point(0,0)] a = [] for i in [0,1,2,0,2,3]: point = points[i] tex = uv[i] a.extend([point.x, point.y, tex.x, tex.y]) # Assign the VBO super(ImageActor, self)._assignVBO(a) self.alpha = float(alpha)
def drawShadowMaps(lights, layerLoc): """ draws shadow maps for debugging. note that a special shader is required to display the depth-component-only textures """ i = 0 for light in lights: if light.shadowMapArray==None: continue shadowMapArray = light.shadowMapArray shadowMaps = shadowMapArray.shadowMaps glBindTexture( GL_TEXTURE_2D_ARRAY, shadowMapArray.texture.glID ) glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_NONE ) for j in range(len(shadowMaps)): glViewport(130*i, 0, 128, 128) glUniform1f(layerLoc, float(j)) glBegin(GL_QUADS) glVertex3f(-1.0, -1.0, 0.0) glVertex3f( 1.0, -1.0, 0.0) glVertex3f( 1.0, 1.0, 0.0) glVertex3f(-1.0, 1.0, 0.0) glEnd() i += 1 if shadowMapArray.textureType=="sampler2DArrayShadow": glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE ) else: glTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_NONE )
def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x + w > ww or y + h > wh: log("do_paint_rgb24: ignoring paint which would overflow the backing area" ) return drawable = self.gl_init() if not drawable: log("do_paint_rgb24: cannot paint yet..") return try: #cleanup if we were doing yuv previously: if self.pixel_format != GLPixmapBacking.RGB24: self.remove_shader() self.pixel_format = GLPixmapBacking.RGB24 glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride / 3) for texture in (GL_TEXTURE1, GL_TEXTURE2): glActiveTexture(texture) glDisable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, GL_RGB, GL_UNSIGNED_BYTE, img_data) glBegin(GL_QUADS) for rx, ry in ((x, y), (x, y + h), (x + w, y + h), (x + w, y)): glTexCoord2i(rx, ry) glVertex2i(rx, ry) glEnd() finally: self.gl_end(drawable)
def load(file_path): img = Image.open(file_path, 'r').convert('RGB') img_data = np.array(img, dtype=np.uint8) width, height = img.size texture = glGenTextures(1) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data) return texture
def load_texture(cls, file_name): texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) # Set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # Set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # load image image = Image.open(file_name) img_data = numpy.array(list(image.getdata()), numpy.uint8) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data) glEnable(GL_TEXTURE_2D) return texture
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format != pixel_format or self.texture_size != ( width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s" % pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width / div_w, height / div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s" % (width, height, pixel_format)) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides) == 3 and len(img_data) == 3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) pixel_data = img_data[index] log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes", index, divs[index], rowstrides[index], width / div_w, height / div_h, len(pixel_data)) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width / div_w, height / div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data)
def load_texture_pygame(path, texture): import pygame glBindTexture(GL_TEXTURE_2D, texture) # Set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # Set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # load image image = pygame.image.load(path) image = pygame.transform.flip(image, False, True) image_width, image_height = image.get_rect().size img_data = pygame.image.tostring(image, "RGBA") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data) return texture
def create(self): tex = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, tex) # Set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # Set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.image) self.tex = tex self.status |= Resource.CREATED
def upload_cursor_texture(self, width, height, pixels): upload, pixel_data = self.pixels_for_upload(pixels) rgb_format = "RGBA" glActiveTexture(GL_TEXTURE0) target = GL_TEXTURE_RECTANGLE_ARB glEnable(target) glBindTexture(target, self.textures[TEX_CURSOR]) self.set_alignment(width, width*4, rgb_format) glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data) log("GL cursor %ix%i uploaded %i bytes of %s pixel data using %s", width, height, len(pixels), rgb_format, upload) glBindTexture(target, 0) glDisable(target)
def bindTexture(self): glBindTexture(GL_TEXTURE_2D, self.texture) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) # These two are only really needed for megatiles; normal # tiles don't have to deal with texture wrapping. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP) img = self.textureData pic_ny, pic_nx = img.shape tex_nx,tex_ny = getTexSize(pic_nx,pic_ny) imgType = img.dtype.type if imgType not in dtypeToGlTypeMap: raise ValueError("Unsupported data mode %s" % str(imgType)) glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, tex_nx,tex_ny, 0, GL_LUMINANCE, dtypeToGlTypeMap[imgType], None)
def upload_cursor_texture(self, target, cursor_data): width = cursor_data[3] height = cursor_data[4] pixels = cursor_data[8] if len(pixels)<width*4*height: log.error("Error: invalid cursor pixel buffer for %ix%i", width, height) log.error(" expected %i bytes but got %i", width*height*4, len(pixels)) log.error(" %s", repr_ellipsized(hexstr(pixels))) return upload, pixel_data = self.pixels_for_upload(pixels) rgb_format = "BGRA" self.set_alignment(width, width*4, rgb_format) glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level(target) glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixel_data) log("GL cursor %ix%i uploaded %i bytes of %s pixel data using %s", width, height, len(pixels), rgb_format, upload)
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert self.textures is not None, "no OpenGL textures!" log("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s", pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width//div_w, height//div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s", width, height, pixel_format) rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 and len(img_data)==3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) upload, pixel_data = self.pixels_for_upload(img_data[index]) log("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes, upload=%s", index, divs[index], rowstrides[index], width//div_w, height//div_h, len(pixel_data), upload) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) try: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) except: pass glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width//div_w, height//div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data)
def update_planar_textures(self, x, y, width, height, img, pixel_format, scaling=False): assert x==0 and y==0 assert self.textures is not None, "no OpenGL textures!" debug("%s.update_planar_textures%s", self, (x, y, width, height, img, pixel_format)) divs = get_subsampling_divs(pixel_format) if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height): self.pixel_format = pixel_format self.texture_size = (width, height) self.gl_marker("Creating new planar textures, pixel format %s" % pixel_format) # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glEnable(GL_TEXTURE_RECTANGLE_ARB) mag_filter = GL_NEAREST if scaling or (div_w > 1 or div_h > 1): mag_filter = GL_LINEAR glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mag_filter) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/div_w, height/div_h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, None) self.gl_marker("updating planar textures: %sx%s %s" % (width, height, pixel_format)) U_width = 0 U_height = 0 rowstrides = img.get_rowstride() img_data = img.get_pixels() assert len(rowstrides)==3 assert len(img_data)==3 for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)): (div_w, div_h) = divs[index] glActiveTexture(texture) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index]) pixel_data = img_data[index][:] debug("texture %s: div=%s, rowstride=%s, %sx%s, data=%s bytes", index, divs[index], rowstrides[index], width/div_w, height/div_h, len(pixel_data)) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data) if index == 1: U_width = width/div_w U_height = height/div_h elif index == 2: if width/div_w != U_width: log.error("Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width/div_w, U_width, pixel_format) if height/div_h != U_height: log.error("Height of V plane is %d, differs from height of corresponding U plane (%d), pixel_format is %d", height/div_h, U_height, pixel_format)
def load_texture(path, tex): """Loads texture from image for GLFW.""" glBindTexture(GL_TEXTURE_2D, tex) # Set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) # Set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # load image image = Image.open(path) image = image.transpose(Image.FLIP_TOP_BOTTOM) img_data = image.convert("RGBA").tobytes() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data) glBindTexture(GL_TEXTURE_2D, 0) return tex
def __init__(self, path): img = Image.open(path) img = img.transpose(Image.FLIP_TOP_BOTTOM) self.m_Width = img.width self.m_Height = img.height self.m_LocalBuffer = img.convert("RGBA").tobytes() self.m_RendererID = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.m_RendererID) # glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, self.m_Width, self.m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, self.m_LocalBuffer) glBindTexture(GL_TEXTURE_2D, 0) if self.m_LocalBuffer: del self.m_LocalBuffer
def _do_paint_rgb(self, bpp, img_data, x, y, width, height, rowstride, options): log("%s._do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d, options=%s)", self, bpp, len(img_data), x, y, width, height, rowstride, options) context = self.gl_context() if not context: log("%s._do_paint_rgb(..) no context!", self) return False #TODO: move this code up to the decode thread section upload, img_data = self.pixels_for_upload(img_data) with context: self.gl_init() self.set_rgb_paint_state() rgb_format = options.get(b"rgb_format") if not rgb_format: #Older servers may not tell us the pixel format, so we must infer it: if bpp==24: rgb_format = "RGB" else: assert bpp==32 rgb_format = "RGBA" else: rgb_format = rgb_format.decode() #convert it to a GL constant: pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format) assert pformat is not None, "could not find pixel format for %s (bpp=%s)" % (rgb_format, bpp) bytes_per_pixel = len(rgb_format) #ie: BGRX -> 4 # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a-1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * bytes_per_pixel) >= alignment: row_length = width + (rowstride - width * bytes_per_pixel) // bytes_per_pixel self.gl_marker("%s %sbpp update at (%d,%d) size %dx%d (%s bytes), stride=%d, row length %d, alignment %d, using GL %s format=%s", rgb_format, bpp, x, y, width, height, len(img_data), rowstride, row_length, alignment, upload, CONSTANT_TO_PIXEL_FORMAT.get(pformat)) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y+height) glTexCoord2i(width, height) glVertex2i(x+width, y+height) glTexCoord2i(width, 0) glVertex2i(x+width, y) glEnd() self.paint_box(options.get("encoding"), options.get("delta", -1)>=0, x, y, width, height) # Present update to screen self.present_fbo(x, y, width, height, options.get("flush", 0)) # present_fbo has reset state already return True
def do_present_fbo(self): self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() bw, bh = self.size ww, wh = self.render_size if self.glconfig.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) #viewport for painting to window: glViewport(0, 0, ww, wh) if ww!=bw or wh!=bh: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(bw/3.0, bh/3.0) t = time.time() count = int(t*4.0) bx = bw//2 by = bh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (bw, 0), (bw, bh), (0, bh)): glVertex2i(px, py) glEnd() # Show the backbuffer on screen self.gl_show() self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def do_present_fbo(self): bw, bh = self.size ww, wh = self.render_size self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() rect_count = len(self.pending_fbo_paint) if self.glconfig.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) if SAVE_BUFFERS: glBindFramebuffer(GL_READ_FRAMEBUFFER, self.offscreen_fbo) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glReadBuffer(GL_COLOR_ATTACHMENT0) glViewport(0, 0, bw, bh) from OpenGL.GL import glGetTexImage size = bw*bh*4 import numpy data = numpy.empty(size) img_data = glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, GL_UNSIGNED_BYTE, data) from PIL import Image, ImageOps img = Image.frombuffer("RGBA", (bw, bh), img_data, "raw", "BGRA", bw*4) img = ImageOps.flip(img) kwargs = {} if SAVE_BUFFERS=="jpeg": kwargs = { "quality" : 0, "optimize" : False, } t = time.time() tstr = time.strftime("%H-%M-%S", time.localtime(t)) filename = "./W%i-FBO-%s.%03i.%s" % (self.wid, tstr, (t*1000)%1000, SAVE_BUFFERS) log("do_present_fbo: saving %4ix%-4i pixels, %7i bytes to %s", bw, bh, size, filename) img.save(filename, SAVE_BUFFERS, **kwargs) glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) #viewport for painting to window: glViewport(0, 0, ww, wh) if ww!=bw or wh!=bh: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(bw/3.0, bh/3.0) t = time.time() count = int(t*4.0) bx = bw//2 by = bh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (bw, 0), (bw, bh), (0, bh)): glVertex2i(px, py) glEnd() if self.pointer_overlay: x, y, _, _, size, start_time = self.pointer_overlay elapsed = time.time()-start_time if elapsed<6: alpha = max(0, (5.0-elapsed)/5.0) glLineWidth(1) glBegin(GL_LINES) glColor4f(0, 0, 0, alpha) glVertex2i(x-size, y) glVertex2i(x+size, y) glVertex2i(x, y-size) glVertex2i(x, y+size) glEnd() else: self.pointer_overlay = None # Show the backbuffer on screen self.gl_show(rect_count) self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def _do_paint_rgb(self, bpp, img_data, x, y, width, height, rowstride, options, callbacks): debug( "%s._do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d)", self, bpp, len(img_data), x, y, width, height, rowstride, ) drawable = self.gl_init() if not drawable: debug("%s._do_paint_rgb(..) drawable is not set!", self) return False try: self.set_rgb_paint_state() bytes_per_pixel = bpp / 8 # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a - 1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * bytes_per_pixel) > a: row_length = width + (rowstride - width * bytes_per_pixel) / bytes_per_pixel rgb_format = options.get("rgb_format", None) self.gl_marker( "%s %sbpp update at %d,%d, size %d,%d, stride is %d, row length %d, alignment %d" % (rgb_format, bpp, x, y, width, height, rowstride, row_length, alignment) ) # Upload data as temporary RGB texture if bpp == 24: if rgb_format == "BGR": pformat = GL_BGR else: assert rgb_format in ("RGB", None), "invalid 24-bit format: %s" % rgb_format pformat = GL_RGB else: assert bpp == 32 if rgb_format == "BGRA": pformat = GL_BGRA else: assert rgb_format in ("RGBA", None), "invalid 32-bit format: %s" % rgb_format pformat = GL_RGBA glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y + height) glTexCoord2i(width, height) glVertex2i(x + width, y + height) glTexCoord2i(width, 0) glVertex2i(x + width, y) glEnd() # Present update to screen self.present_fbo(drawable) # present_fbo has reset state already finally: drawable.gl_end() return True
def do_paint_rgb(self, rgb_format, img_data, x, y, width, height, rowstride, options, callbacks): log("%s.do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d, options=%s)", self, rgb_format, len(img_data), x, y, width, height, rowstride, options) context = self.gl_context() if not context: log("%s._do_paint_rgb(..) no context!", self) fire_paint_callbacks(callbacks, False, "no opengl context") return if not options.get("paint", True): fire_paint_callbacks(callbacks) return try: upload, img_data = self.pixels_for_upload(img_data) with context: self.gl_init() self.set_rgb_paint_state() #convert it to a GL constant: pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format.decode()) assert pformat is not None, "could not find pixel format for %s" % rgb_format bytes_per_pixel = len(rgb_format) #ie: BGRX -> 4 # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a-1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * bytes_per_pixel) >= alignment: row_length = width + (rowstride - width * bytes_per_pixel) // bytes_per_pixel self.gl_marker("%s update at (%d,%d) size %dx%d (%s bytes), stride=%d, row length %d, alignment %d, using GL %s format=%s", rgb_format, x, y, width, height, len(img_data), rowstride, row_length, alignment, upload, CONSTANT_TO_PIXEL_FORMAT.get(pformat)) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) set_texture_level() glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y+height) glTexCoord2i(width, height) glVertex2i(x+width, y+height) glTexCoord2i(width, 0) glVertex2i(x+width, y) glEnd() self.paint_box(options.get("encoding"), options.get("delta", -1)>=0, x, y, width, height) # Present update to screen self.present_fbo(x, y, width, height, options.get("flush", 0)) # present_fbo has reset state already fire_paint_callbacks(callbacks) except Exception as e: log("Error in %s paint of %i bytes, options=%s)", rgb_format, len(img_data), options) fire_paint_callbacks(callbacks, False, "OpenGL %s paint error: %s" % (rgb_format, e))
def _set_wrap(self, wrap): if wrap == self._gl_wrap: return self.bind() glTexParameteri(self.target, GL_TEXTURE_WRAP_S, wrap) glTexParameteri(self.target, GL_TEXTURE_WRAP_T, wrap)
def _set_mag_filter(self, x): if x == self._gl_mag_filter: return self.bind() glTexParameteri(self.target, GL_TEXTURE_MAG_FILTER, x) self._gl_mag_filter = x
def create(width, height, format=GL_RGBA, rectangle=False, mipmap=False): '''Create a texture based on size.''' target = GL_TEXTURE_2D if rectangle: if _is_pow2(width) and _is_pow2(height): rectangle = False else: rectangle = False try: if Texture._has_texture_nv is None: Texture._has_texture_nv = glInitTextureRectangleNV() if Texture._has_texture_nv: target = GL_TEXTURE_RECTANGLE_NV rectangle = True except Exception: pass try: if Texture._has_texture_arb is None: Texture._has_texture_arb = glInitTextureRectangleARB() if not rectangle and Texture._has_texture_arb: target = GL_TEXTURE_RECTANGLE_ARB rectangle = True except Exception: pass if not rectangle: pymt_logger.debug( 'Texture: Missing support for rectangular texture') else: # Can't do mipmap with rectangle texture mipmap = False if rectangle: texture_width = width texture_height = height else: texture_width = _nearest_pow2(width) texture_height = _nearest_pow2(height) texid = glGenTextures(1) texture = Texture(texture_width, texture_height, target, texid, mipmap=mipmap) texture.bind() texture.wrap = GL_CLAMP_TO_EDGE if mipmap: texture.min_filter = GL_LINEAR_MIPMAP_LINEAR #texture.mag_filter = GL_LINEAR_MIPMAP_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE) else: texture.min_filter = GL_LINEAR texture.mag_filter = GL_LINEAR if not Texture.is_gl_format_supported(format): format = Texture.convert_gl_format(format) data = (GLubyte * texture_width * texture_height * Texture.gl_format_size(format))() glTexImage2D(target, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, data) if rectangle: texture.tex_coords = \ (0., 0., width, 0., width, height, 0., height) glFlush() if texture_width == width and texture_height == height: return texture return texture.get_region(0, 0, width, height)
def setup(self): ''' Construct the texture atlas for the font ''' face = Face(self.filename) face.set_pixel_sizes(0, self.size) rowh, roww = 0,0 # Determine image size for i in xrange(32,128): face.load_char( chr(i), FT_LOAD_RENDER) bitmap = face.glyph.bitmap if roww + bitmap.width + 1 >= 1024: # max texture width self.w = max(self.w, roww) self.h += rowh roww = 0 rowh = 0 roww += bitmap.width + 1 rowh = max(rowh, bitmap.rows) self.w = max(self.w, roww) self.h += rowh ## Create texture to hold ASCII glyphs # Ensure no texture is currently selected glActiveTexture(GL_TEXTURE0) self.texid = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, self.texid) glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, self.w, self.h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0) # We require 1 byte alignment when uploading texture data glPixelStorei(GL_UNPACK_ALIGNMENT, 1) # Clamping to edges is important to prevent artifacts when scaling glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) # Linear filtering looks better for text glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) # Add glyphs to texture ox = 0 oy = 0 rowh = 0 # class to hold data class CharInfo: pass for i in xrange(32,128): face.load_char( chr(i), FT_LOAD_RENDER) g = face.glyph bitmap = g.bitmap if ox + bitmap.width + 1 >= 1024: # max texture width oy += rowh rowh = 0 ox = 0 glTexSubImage2D(GL_TEXTURE_2D, 0, ox, oy, bitmap.width, bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer) ci = CharInfo() ci.ax = float(g.advance.x >> 6) ci.ay = float(g.advance.y >> 6) ci.bw = float(bitmap.width) ci.bh = float(bitmap.rows) ci.bl = float(g.bitmap_left) ci.bt = float(g.bitmap_top) ci.tx = float(ox) / float(self.w) ci.ty = float(oy) / float(self.h) self.c[chr(i)] = ci rowh = max(rowh, bitmap.rows) ox += bitmap.width + 1
def gl_init(self): drawable = self.gl_begin() w, h = self.size debug("%s.gl_init() GL Pixmap backing size: %d x %d, drawable=%s", self, w, h, drawable) if not drawable: return None if not self.gl_setup: #ensure python knows which scope we're talking about: global glInitStringMarkerGREMEDY, glStringMarkerGREMEDY global glInitFrameTerminatorGREMEDY, glFrameTerminatorGREMEDY # Ask GL to send us all debug messages if GL_DEBUG_OUTPUT and gl_debug_callback and glInitDebugKHR() == True: glEnable(GL_DEBUG_OUTPUT) glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS) glDebugMessageCallback(gl_debug_callback, None) glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, None, GL_TRUE) # Initialize string_marker GL debugging extension if available if glInitStringMarkerGREMEDY and glInitStringMarkerGREMEDY() == True: log.info("Extension GL_GREMEDY_string_marker available. Will output detailed information about each frame.") else: # General case - running without debugger, extension not available glStringMarkerGREMEDY = None #don't bother trying again for another window: glInitStringMarkerGREMEDY = None # Initialize frame_terminator GL debugging extension if available if glInitFrameTerminatorGREMEDY and glInitFrameTerminatorGREMEDY() == True: log.info("Enabling GL frame terminator debugging.") else: glFrameTerminatorGREMEDY = None #don't bother trying again for another window: glInitFrameTerminatorGREMEDY = None self.gl_marker("Initializing GL context for window size %d x %d" % (w, h)) # Initialize viewport and matrices for 2D rendering glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) #TODO glEnableClientState(GL_VERTEX_ARRAY) #TODO glEnableClientState(GL_TEXTURE_COORD_ARRAY) # Clear to white glClearColor(1.0, 1.0, 1.0, 1.0) # Default state is good for YUV painting: # - fragment program enabled # - YUV fragment program bound # - render to offscreen FBO glEnable(GL_FRAGMENT_PROGRAM_ARB) if self.textures is None: self.textures = glGenTextures(5) debug("%s.gl_init() textures of size %s : %s", self, self.size, self.textures) if self.offscreen_fbo is None: self.offscreen_fbo = glGenFramebuffers(1) # Define empty FBO texture and set rendering to FBO glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) # nvidia needs this even though we don't use mipmaps (repeated through this file): glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, None) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glClear(GL_COLOR_BUFFER_BIT) # Create and assign fragment programs if not self.shaders: self.shaders = [ 1, 2 ] glGenProgramsARB(2, self.shaders) for progid, progstr in ((0, YUV2RGB_shader), (1, RGBP2RGB_shader)): glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[progid]) glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(progstr), progstr) err = glGetString(GL_PROGRAM_ERROR_STRING_ARB) if err: #FIXME: maybe we should do something else here? log.error(err) # Bind program 0 for YUV painting by default glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[0]) self.gl_setup = True return drawable
def _do_paint_rgb(self, bpp, img_data, x, y, width, height, rowstride, options): log("%s._do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d)", self, bpp, len(img_data), x, y, width, height, rowstride) drawable = self.gl_init() if not drawable: log("%s._do_paint_rgb(..) drawable is not set!", self) return False #deal with buffers uploads by wrapping them if we can, or copy to a string: if type(img_data)==buffer: if memoryview_type is not None: img_data = memoryview_type(img_data) else: img_data = str(img_data) try: self.set_rgb_paint_state() rgb_format = options.get("rgb_format") if not rgb_format: #Older servers may not tell us the pixel format, so we must infer it: if bpp==24: rgb_format = "RGB" else: assert bpp==32 rgb_format = "RGBA" #convert it to a GL constant: pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format) assert pformat is not None, "could not find pixel format for %s (bpp=%s)" % (rgb_format, bpp) bytes_per_pixel = len(rgb_format) #ie: BGRX -> 4 # Compute alignment and row length row_length = 0 alignment = 1 for a in [2, 4, 8]: # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on if (rowstride & a-1) == 0: alignment = a # If number of extra bytes is greater than the alignment value, # then we also have to set row_length # Otherwise it remains at 0 (= width implicitely) if (rowstride - width * bytes_per_pixel) >= alignment: row_length = width + (rowstride - width * bytes_per_pixel) / bytes_per_pixel self.gl_marker("%s %sbpp update at (%d,%d) size %dx%d (%s bytes), stride=%d, row length %d, alignment %d, using GL upload format=%s" % (rgb_format, bpp, x, y, width, height, len(img_data), rowstride, row_length, alignment, CONSTANT_TO_PIXEL_FORMAT.get(pformat))) # Upload data as temporary RGB texture glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) # Draw textured RGB quad at the right coordinates glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, height) glVertex2i(x, y+height) glTexCoord2i(width, height) glVertex2i(x+width, y+height) glTexCoord2i(width, 0) glVertex2i(x+width, y) glEnd() # Present update to screen self.present_fbo(drawable) # present_fbo has reset state already finally: drawable.gl_end() return True
def update_texture_yuv420(self, img_data, x, y, width, height, rowstrides): drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() window_width, window_height = self.get_size() if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") assert self.textures is not None if self.current_mode == GLClientWindow.MODE_RGB: raise Exception("** RGB -> YUV mode change unimplemented!") elif self.current_mode == GLClientWindow.MODE_UNINITIALIZED: log("Creating new YUV textures") # Create textures of the same size as the window's glEnable(GL_TEXTURE_RECTANGLE_ARB) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width, window_height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/2, window_height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, window_width/2, window_height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); log("Assigning fragment program") glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv420_shader: self.yuv420_shader = [ 1 ] glGenProgramsARB(1, self.yuv420_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) prog = GL_COLORSPACE_CONVERSIONS glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) log.error(glGetString(GL_PROGRAM_ERROR_STRING_ARB)) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) self.current_mode = GLClientWindow.MODE_YUV # Clamp width and height to the actual texture size if x + width > window_width: width = window_width - x if y + height > window_height: height = window_height - y glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[0]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[0]) glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[1]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[1]) glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[2]) glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/2, height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[2]) drawable.gl_end() self.render_image()