def get_shader(self): record_program = Program() record_program.shaders.append(Shader(GL_VERTEX_SHADER, """ #version 410 in vec2 vertex_position; in vec2 text_coord; out vec2 frag_tex_coord; mat3 transformation; void main() { transformation = mat3( vec3(1,0,0), vec3(0,-1,0), vec3(0,0,1) ); frag_tex_coord = text_coord; gl_Position = vec4((transformation*vec3(vertex_position,1)).xy, 0, 1); }""")) record_program.shaders.append(Shader(GL_FRAGMENT_SHADER, """ #version 410 in vec2 frag_tex_coord; out vec4 output_color; uniform sampler2D tex[1]; mat2 derp; void main() { derp[0].x = 1; derp[0].y = 0; derp[1].x = 0; derp[1].y = 1; output_color = texture(tex[0], derp*frag_tex_coord); output_color.w = %f; } """%self.w)) record_program.link() return record_program
def init(self): """ prepares shaders and vao/vbo """ # init gl program = Program() vertex_shader = Shader(GL_VERTEX_SHADER, load_lib_file('glsl/font/font.vert.glsl')) fragment_shader = Shader(GL_FRAGMENT_SHADER, load_lib_file('glsl/font/font.frag.glsl')) program.shaders.append(vertex_shader) program.shaders.append(fragment_shader) program.link() self.program = program self.camera.on_change_matrix.append(self.camera_updated)
def init(self): glEnable( GL_MULTISAMPLE ) """ initializes shader program, framebuffer and plane vao/vbo """ # default shader program if self.program is None: program = Program() vertex_shader = Shader(GL_VERTEX_SHADER, load_lib_file('glsl/framewindow.vert.glsl')) fragment_shader = Shader(GL_FRAGMENT_SHADER, load_lib_file('glsl/framewindow.frag.glsl')) program.shaders.append(vertex_shader) program.shaders.append(fragment_shader) program.link() self.program = program # default complex record shader program if self.record_mode == Framebuffer.RECORD_TRACK_COMPLEX and self.record_program is None: program = Program() vertex_shader = Shader(GL_VERTEX_SHADER, load_lib_file('glsl/framewindow_record.vert.glsl')) fragment_shader = Shader(GL_FRAGMENT_SHADER, load_lib_file('glsl/framewindow_record.frag.glsl')) program.shaders.append(vertex_shader) program.shaders.append(fragment_shader) program.link() self.record_program = program self.init_capturing() self.init_screen() self.update_camera(self.camera) self.update_modelview()
def gl_init(self): """ initializes shader program and plane vao """ glsl_functions = "" if hasattr(self.color_scheme, "glsl_functions"): glsl_functions += "\n/*COLOR_SCHEME FUNCTIONS*/\n" glsl_functions += self.color_scheme.glsl_functions if hasattr(self.data_kernel, "glsl_functions"): glsl_functions += "\n/*DATA_KERNEL FUNCTIONS*/\n" glsl_functions += self.data_kernel.glsl_functions glsl_uniforms = [] if hasattr(self.color_scheme, "glsl_uniforms"): glsl_uniforms.append("/*COLOR_SCHEME UNIFORMS*/") glsl_uniforms += ["uniform {} {};".format(t, n) for t, n in self.color_scheme.glsl_uniforms] if hasattr(self.data_kernel, "glsl_uniforms"): glsl_uniforms.append("/*DATA_KERNEL UNIFORMS*/") glsl_uniforms += ["uniform {} {};".format(t, n) for t, n in self.data_kernel.glsl_uniforms] frag_src = pystache.render( load_lib_file("glsl/plot2d/field.frag.glsl"), { "UNIFORMS": "\n".join(glsl_uniforms), "FUNCTIONS": glsl_functions, "DATA_KERNEL": str(self.data_kernel), "COLOR_KERNEL": str(self.color_scheme), }, ) self.program = Program() self.program.shaders.append(Shader(GL_VERTEX_SHADER, load_lib_file("glsl/plot2d/field.vert.glsl"))) self.program.shaders.append(Shader(GL_FRAGMENT_SHADER, frag_src)) self.program.link() if hasattr(self.color_scheme, "get_uniform_data"): for uniform in self.color_scheme.get_uniform_data().items(): self.program.uniform(*uniform) if hasattr(self.data_kernel, "get_uniform_data"): for uniform in self.data_kernel.get_uniform_data().items(): self.program.uniform(*uniform) self.initialized = True
def init(self): # load font file self._fnt = FNTFile.load_from_file(self.font_path) # upload glyph 3d atlas page_data = [imread(img_path)[:,:,3] for img_path in self._fnt.page_paths] glypthatlas_width = page_data[0].shape[0] glyphatlas_height = page_data[0].shape[1] glyphatlas = np.empty((len(page_data), glypthatlas_width, glyphatlas_height), dtype=np.float32) for i, glyphdata in enumerate(page_data): if glyphdata.shape[0:2] != (glypthatlas_width,glyphatlas_height): raise Exception(( 'font "{}" corrupt: font page id={} file="{}" image size {}x{}' + ' differs from the first page id=0 file="{}" {}x{}').format( self.font, i, self._fnt.page_paths[i], glyphdata.shape[0], glyphdata.shape[1], self._fnt.page_paths[0], page_data[0].shape[0], page_data[0].shape[1])) glyphatlas[i] = glyphdata self.texture_id = glGenTextures(1); glBindTexture(GL_TEXTURE_2D_ARRAY, self.texture_id); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, glypthatlas_width, glyphatlas_height, glyphatlas.shape[0], 0, GL_RED, GL_FLOAT, glyphatlas); glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBindTexture(GL_TEXTURE_2D_ARRAY, 0); # create shader self.shader_program = Program() self.shader_program.shaders.append(Shader(GL_VERTEX_SHADER, VERTEX_SHADER)) self.shader_program.shaders.append(Shader(GL_GEOMETRY_SHADER, GEOMETRY_SHADER.replace('$n$', str(len(self._fnt.glyphs))))) self.shader_program.shaders.append(Shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER.replace('$n$', str(len(self._fnt.glyphs))))) self.shader_program.link() # create vbo/vao self.buffer = BufferObject.empty(1, dtype=self.CHAR_DTYPE) self.vao = glGenVertexArrays(1) # bind vao glBindVertexArray(self.vao) self.buffer.bind() itemsize = c_int(self.CHAR_DTYPE.itemsize) glVertexAttribPointer(self.shader_program.attributes['vertex_position'], 2, GL_FLOAT, GL_FALSE, itemsize, c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer(self.shader_program.attributes['glyph_color'], 4, GL_FLOAT, GL_FALSE, itemsize, c_void_p(8)) glEnableVertexAttribArray(1) glVertexAttribPointer(self.shader_program.attributes['glyph_size'], 1, GL_FLOAT, GL_FALSE, itemsize, c_void_p(24)) glEnableVertexAttribArray(2) glVertexAttribPointer(self.shader_program.attributes['glyph_rot'], 1, GL_FLOAT, GL_FALSE, itemsize, c_void_p(28)) glEnableVertexAttribArray(3) glVertexAttribIPointer(self.shader_program.attributes['fntobj'], 1, GL_INT, itemsize, c_void_p(32)) glEnableVertexAttribArray(4) self.buffer.unbind() glBindVertexArray(0) # upload glyph information glyphdata = np.empty(len(self._fnt.glyphs), dtype=self.GLYPH_DTYPE) glyphdata[:] = [c.dump() for c in self._fnt.glyphs] self.font_buffer = BufferObject.to_device(glyphdata, target=GL_UNIFORM_BUFFER) self.font_buffer.bind_buffer_base(0) block_index = glGetUniformBlockIndex(self.shader_program.gl_id, "ubo_font_objects") if block_index == GL_INVALID_INDEX: raise Exception('wo is der block was') glUniformBlockBinding(self.shader_program.gl_id, block_index, self.font_buffer.gl_buffer_base) self.shader_program.uniform('tex_scale', [1.0/glypthatlas_width, 1.0/glyphatlas_height]) self.shader_program.uniform('fontsize_real', 60) self.shader_program.uniform('tex', 1) if self.camera: self.shader_program.uniform('mat_camera', self.camera.get_matrix()) self.camera_changed = False for text in self.texts: text.font = self._fnt
class FontRenderer(): CHAR_DTYPE = np.dtype([ ('position', np.float32, (2,)), ('color', np.float32, (4,)), ('size', np.float32), ('rot', np.float32), ('fntobj', np.int32), ]) GLYPH_DTYPE = np.dtype([ ('position', np.float32, (4,)), ('size', np.float32, (4,)), ('offset', np.float32, (4,)), ('xadvance', np.float32), ('page', np.float32), ('chnl', np.float32), ('buff', np.float32), ]) def __init__(self, font=None): self.camera = None if font is None: font = os.path.join(FONT_FOLDER, 'arial.fnt') self.font_path = font self.texts = [] self._has_changes = True self._fnt = None @property def font(self): return self._fnt def init(self): # load font file self._fnt = FNTFile.load_from_file(self.font_path) # upload glyph 3d atlas page_data = [imread(img_path)[:,:,3] for img_path in self._fnt.page_paths] glypthatlas_width = page_data[0].shape[0] glyphatlas_height = page_data[0].shape[1] glyphatlas = np.empty((len(page_data), glypthatlas_width, glyphatlas_height), dtype=np.float32) for i, glyphdata in enumerate(page_data): if glyphdata.shape[0:2] != (glypthatlas_width,glyphatlas_height): raise Exception(( 'font "{}" corrupt: font page id={} file="{}" image size {}x{}' + ' differs from the first page id=0 file="{}" {}x{}').format( self.font, i, self._fnt.page_paths[i], glyphdata.shape[0], glyphdata.shape[1], self._fnt.page_paths[0], page_data[0].shape[0], page_data[0].shape[1])) glyphatlas[i] = glyphdata self.texture_id = glGenTextures(1); glBindTexture(GL_TEXTURE_2D_ARRAY, self.texture_id); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, glypthatlas_width, glyphatlas_height, glyphatlas.shape[0], 0, GL_RED, GL_FLOAT, glyphatlas); glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBindTexture(GL_TEXTURE_2D_ARRAY, 0); # create shader self.shader_program = Program() self.shader_program.shaders.append(Shader(GL_VERTEX_SHADER, VERTEX_SHADER)) self.shader_program.shaders.append(Shader(GL_GEOMETRY_SHADER, GEOMETRY_SHADER.replace('$n$', str(len(self._fnt.glyphs))))) self.shader_program.shaders.append(Shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER.replace('$n$', str(len(self._fnt.glyphs))))) self.shader_program.link() # create vbo/vao self.buffer = BufferObject.empty(1, dtype=self.CHAR_DTYPE) self.vao = glGenVertexArrays(1) # bind vao glBindVertexArray(self.vao) self.buffer.bind() itemsize = c_int(self.CHAR_DTYPE.itemsize) glVertexAttribPointer(self.shader_program.attributes['vertex_position'], 2, GL_FLOAT, GL_FALSE, itemsize, c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer(self.shader_program.attributes['glyph_color'], 4, GL_FLOAT, GL_FALSE, itemsize, c_void_p(8)) glEnableVertexAttribArray(1) glVertexAttribPointer(self.shader_program.attributes['glyph_size'], 1, GL_FLOAT, GL_FALSE, itemsize, c_void_p(24)) glEnableVertexAttribArray(2) glVertexAttribPointer(self.shader_program.attributes['glyph_rot'], 1, GL_FLOAT, GL_FALSE, itemsize, c_void_p(28)) glEnableVertexAttribArray(3) glVertexAttribIPointer(self.shader_program.attributes['fntobj'], 1, GL_INT, itemsize, c_void_p(32)) glEnableVertexAttribArray(4) self.buffer.unbind() glBindVertexArray(0) # upload glyph information glyphdata = np.empty(len(self._fnt.glyphs), dtype=self.GLYPH_DTYPE) glyphdata[:] = [c.dump() for c in self._fnt.glyphs] self.font_buffer = BufferObject.to_device(glyphdata, target=GL_UNIFORM_BUFFER) self.font_buffer.bind_buffer_base(0) block_index = glGetUniformBlockIndex(self.shader_program.gl_id, "ubo_font_objects") if block_index == GL_INVALID_INDEX: raise Exception('wo is der block was') glUniformBlockBinding(self.shader_program.gl_id, block_index, self.font_buffer.gl_buffer_base) self.shader_program.uniform('tex_scale', [1.0/glypthatlas_width, 1.0/glyphatlas_height]) self.shader_program.uniform('fontsize_real', 60) self.shader_program.uniform('tex', 1) if self.camera: self.shader_program.uniform('mat_camera', self.camera.get_matrix()) self.camera_changed = False for text in self.texts: text.font = self._fnt def set_camera(self, camera): self.camera = camera self.camera_changed = True def create_text(self, text, size=10, position=(0,0), color=[0,0,0,1], rotation=0, **kwargs): """ creates a text with certain size, position and rotation. :text: the text to be rendered :size: size of the text :position: position on xy plane :rotation: angle to rotate aroung (position.x, position.y) in mathematical way (anti clockwise). np.pi/2 = 90° np.pi = 180° np.pi*3/2 = 270° 2*pi = 360° returns a TextObject instance. """ textobj = TextObject(self, text, size, position, color=color, rotation=rotation, **kwargs) self.texts.append(textobj) self._has_changes = True return textobj def clear_texts(self): self.texts = [] self._has_changes = True def render(self): self._dummybufferstuff() if self.camera_changed: self.shader_program.uniform('mat_camera', self.camera.get_matrix()) # prepare glClearColor(1,1,1,1) glActiveTexture(GL_TEXTURE1) # XXX disale texture later?? glBindTexture (GL_TEXTURE_2D_ARRAY, int(self.texture_id)) glEnable (GL_BLEND) glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) # render glBindVertexArray(self.vao) self.shader_program.use() glDrawArrays(GL_POINTS, 0, self.buffer.shape[0]) self.shader_program.unuse() glBindVertexArray(0) def _dummybufferstuff(self): # XXX # think about me, # intelligent partitioning and bla if self._has_changes: nchars = 0 for textobj in self.texts: nchars += len(textobj) chardata = np.empty(nchars, dtype=self.CHAR_DTYPE) index = 0 for textobj in self.texts: data = textobj.get_data() chardata[index:index+len(data)] = data index += len(data) self.buffer.set(chardata) self._has_changes = False
class Field: """ draw a 2d field by using Field Domain (OpenGL textures). this plot runs either with or without a given FieldDomain(texture). If no domain defined, the field will scale to top_left, bottom_right. the data_kernel can be used to calculate data where domain is [0,1] x [0,1]. if domain is not None, that top_left, bottom_right will be the center of top_left and bottom_right texel. data_kernel is by default the default glsl 2d texture sampler. using a color scheme one can modify data from data_kernel. (field plot color scheme...) """ def __init__(self, domain=None, top_left=None, bottom_right=None, color_scheme=None, data_kernel=None): if domain is None and data_kernel is None: raise ValueError("either domain or data_kernel must be defined.") self.top_left = top_left or None self.bottom_right = bottom_right or None self.domain = domain self.color_scheme = color_scheme or "" self.initialized = False self.program = None self.data_kernel = data_kernel or "fragment_color = texture(tex[0], x);" self._np_vertex_data = None self._np_texture_data = None self._coord_top_left = None self._coord_bottom_right = None def init(self): if self.domain is not None: if not hasattr(self.domain, "dimensions"): raise ValueError("domain must have attribute domain.dimensions") if not hasattr(self.domain, "gl_texture_id"): raise ValueError("domain must have attribute domain.gl_texture_id") self.domain.gl_init() if self.top_left is None: self.top_left = (1, self.domain.dimensions[1]) if self.bottom_right is None: self.bottom_right = (self.domain.dimensions[0], 1) self.gl_init() self._np_texture_data = np.array([0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], dtype=np.float32).reshape(6, 2) self.scale(self.top_left, self.bottom_right) self.initialized = True def scale(self, top_left, bottom_right): """ scales to field to a rectangle with top_left and bottom_right corner """ if self.domain is None: self._coord_top_left = top_left or (0, 1) self._coord_bottom_right = bottom_right or (1, 0) else: dimensions = (self.domain.dimensions[0] - 1, self.domain.dimensions[1] - 1) unit_size_x = 0.5 * float(bottom_right[0] - top_left[0]) / dimensions[1] unit_size_y = 0.5 * float(top_left[1] - bottom_right[1]) / dimensions[0] self._coord_top_left = (top_left[0] - unit_size_x, top_left[1] + unit_size_y) self._coord_bottom_right = (bottom_right[0] + unit_size_x, bottom_right[1] - unit_size_y) self._np_vertex_data = np.array( [ self._coord_top_left[0], self._coord_top_left[1], self._coord_top_left[0], self._coord_bottom_right[1], self._coord_bottom_right[0], self._coord_bottom_right[1], self._coord_bottom_right[0], self._coord_bottom_right[1], self._coord_bottom_right[0], self._coord_top_left[1], self._coord_top_left[0], self._coord_top_left[1], ], dtype=np.float32, ).reshape(6, 2) self.vertex_array = VertexArray( { "vertex_position": VertexBuffer.from_numpy(self._np_vertex_data), "texture_position": VertexBuffer.from_numpy(self._np_texture_data), }, self.program.attributes, ) self.top_left = top_left self.bottom_right = bottom_right def gl_init(self): """ initializes shader program and plane vao """ glsl_functions = "" if hasattr(self.color_scheme, "glsl_functions"): glsl_functions += "\n/*COLOR_SCHEME FUNCTIONS*/\n" glsl_functions += self.color_scheme.glsl_functions if hasattr(self.data_kernel, "glsl_functions"): glsl_functions += "\n/*DATA_KERNEL FUNCTIONS*/\n" glsl_functions += self.data_kernel.glsl_functions glsl_uniforms = [] if hasattr(self.color_scheme, "glsl_uniforms"): glsl_uniforms.append("/*COLOR_SCHEME UNIFORMS*/") glsl_uniforms += ["uniform {} {};".format(t, n) for t, n in self.color_scheme.glsl_uniforms] if hasattr(self.data_kernel, "glsl_uniforms"): glsl_uniforms.append("/*DATA_KERNEL UNIFORMS*/") glsl_uniforms += ["uniform {} {};".format(t, n) for t, n in self.data_kernel.glsl_uniforms] frag_src = pystache.render( load_lib_file("glsl/plot2d/field.frag.glsl"), { "UNIFORMS": "\n".join(glsl_uniforms), "FUNCTIONS": glsl_functions, "DATA_KERNEL": str(self.data_kernel), "COLOR_KERNEL": str(self.color_scheme), }, ) self.program = Program() self.program.shaders.append(Shader(GL_VERTEX_SHADER, load_lib_file("glsl/plot2d/field.vert.glsl"))) self.program.shaders.append(Shader(GL_FRAGMENT_SHADER, frag_src)) self.program.link() if hasattr(self.color_scheme, "get_uniform_data"): for uniform in self.color_scheme.get_uniform_data().items(): self.program.uniform(*uniform) if hasattr(self.data_kernel, "get_uniform_data"): for uniform in self.data_kernel.get_uniform_data().items(): self.program.uniform(*uniform) self.initialized = True def update_plotmeta(self, plot_cam, outer_cam, *args, **kwargs): # not so nice ... but later refactoring ... self.program.uniform("mat_domain", np.identity(3)) self.program.uniform("mat_camera", plot_cam) self.program.uniform("mat_outer_camera", outer_cam) if hasattr(self.color_scheme, "get_uniform_data"): for uniform in self.color_scheme.get_uniform_data().items(): self.program.uniform(*uniform) if hasattr(self.data_kernel, "get_uniform_data"): for uniform in self.data_kernel.get_uniform_data().items(): self.program.uniform(*uniform) def render(self, plotter): # final rendering glActiveTexture(GL_TEXTURE0) if self.domain is not None: glBindTexture(GL_TEXTURE_2D, self.domain.gl_texture_id) else: glBindTexture(GL_TEXTURE_2D, 0) self.vertex_array.bind() self.program.use() glDrawArrays(GL_TRIANGLES, 0, 6) self.vertex_array.unbind() self.program.unuse() @classmethod def create_texture1f(cls, size): texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, texture) glTexImage2D( GL_TEXTURE_2D, 0, GL_RED, size[0], size[1], 0, GL_RED, GL_FLOAT, np.zeros(size[0] * size[1], dtype=np.float32), ) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glBindTexture(GL_TEXTURE_2D, 0) return texture