def mirror_framebuffer(self, src, src_x=0, src_y=0, src_w=0, src_h=0, dst_x=0, dst_y=0, dst_w=0, dst_h=0, target=GL_COLOR_BUFFER_BIT, filter_type=GL_LINEAR): glBindFramebuffer(GL_READ_FRAMEBUFFER, src.buffer) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.buffer) if GL_COLOR_BUFFER_BIT == target: glDrawBuffers(1, (GL_COLOR_ATTACHMENT0, )) glReadBuffer(GL_COLOR_ATTACHMENT0) elif GL_DEPTH_BUFFER_BIT == target and src.depth_texture is not None: attachment = OpenGLContext.get_depth_attachment( src.depth_texture.internal_format) glDrawBuffers(1, (attachment, )) glReadBuffer(attachment) glBlitFramebuffer(src_w or src.viewport_width, src_y, src_x, src_h or src.viewport_height, dst_x, dst_y, dst_w or self.viewport_width, dst_h or self.viewport_height, target, filter_type)
def get_image_data(self, level=0): if self.target not in (GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D): return None level = min(level, self.get_mipmap_count()) dtype = get_numpy_dtype(self.data_type) try: glBindTexture(self.target, self.buffer) data = OpenGLContext.glGetTexImage(self.target, level, self.texture_format, self.data_type) # convert to numpy array if type(data) is bytes: data = np.fromstring(data, dtype=dtype) else: data = np.array(data, dtype=dtype) glBindTexture(self.target, 0) return data except: logger.error(traceback.format_exc()) logger.error('%s failed to get image data.' % self.name) logger.info('Try to glReadPixels.') glBindTexture(self.target, self.buffer) fb = glGenFramebuffers(1) glBindFramebuffer(GL_FRAMEBUFFER, fb) data = [] for layer in range(self.depth): if GL_TEXTURE_2D == self.target: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.buffer, level) elif GL_TEXTURE_3D == self.target: glFramebufferTexture3D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_3D, self.buffer, level, layer) elif GL_TEXTURE_2D_ARRAY == self.target: glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, self.buffer, level, layer) glReadBuffer(GL_COLOR_ATTACHMENT0) width, height = self.get_mipmap_size(level) pixels = glReadPixels(0, 0, width, height, self.texture_format, self.data_type) # convert to numpy array if type(pixels) is bytes: pixels = np.fromstring(pixels, dtype=dtype) data.append(pixels) data = np.array(data, dtype=dtype) glBindTexture(self.target, 0) glBindFramebuffer(GL_FRAMEBUFFER, 0) glDeleteFramebuffers(1, [ fb, ]) return data
def generate_framebuffer(self, target_face=GL_TEXTURE_CUBE_MAP_POSITIVE_X, target_layer=0, target_level=0): if self.buffer is None: self.buffer = glGenFramebuffers(1) glBindFramebuffer(GL_FRAMEBUFFER, self.buffer) self.target_face = target_face self.target_layer = target_layer self.target_level = target_level # bind color textures layer_offset = 0 last_texture = None for i, color_texture in enumerate(self.color_textures): if last_texture != color_texture: layer_offset = 0 last_texture = color_texture else: layer_offset += 1 if color_texture is not None: self.attachment_framebuffer(GL_COLOR_ATTACHMENT0 + i, color_texture.target, color_texture.buffer, layer_offset) if self.attach_count > 0: glDrawBuffers(self.attach_count, self.attachments) else: glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) # bind depth texture if self.depth_texture is not None: attachment = OpenGLContext.get_depth_attachment(self.depth_texture.internal_format) self.attachment_framebuffer(attachment, self.depth_texture.target, self.depth_texture.buffer) else: glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0) gl_error = glCheckFramebufferStatus(GL_FRAMEBUFFER) if gl_error != GL_FRAMEBUFFER_COMPLETE: error_message = "glCheckFramebufferStatus error %s." % self.get_error(gl_error) logger.error(error_message) raise BaseException(error_message)
def build_command(self): self.commands.clear() self.add_command(glBindFramebuffer, GL_FRAMEBUFFER, self.buffer) # bind color textures layer_offset = 0 last_texture = None for i, color_texture in enumerate(self.color_textures): if last_texture != color_texture: layer_offset = 0 last_texture = color_texture else: layer_offset += 1 attachment = GL_COLOR_ATTACHMENT0 + i if color_texture is not None: self.add_command(self.func_bind_framebuffer, attachment, color_texture.target, color_texture.buffer, layer_offset) if self.attach_count > 0: self.add_command(glDrawBuffers, self.attach_count, self.attachments) else: self.add_command(glDrawBuffer, GL_NONE) self.add_command(glReadBuffer, GL_NONE) # bind depth texture if self.depth_texture is not None: attachment = OpenGLContext.get_depth_attachment( self.depth_texture.internal_format) self.add_command(self.func_bind_framebuffer, attachment, self.depth_texture.target, self.depth_texture.buffer) else: self.add_command(glFramebufferTexture, GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0)
def use_program(self): OpenGLContext.use_program(self.program)
def delete(self): OpenGLContext.use_program(0) glDeleteProgram(self.program) logger.info("Deleted %s material." % self.name)