def init_gl(self, glcontext): assert not self.shader assert glcontext == self.glcontext frag_stage = GstGL.GLSLStage.new_default_fragment(self.glcontext) vert_stage = GstGL.GLSLStage.new_with_string( self.glcontext, GL_VERTEX_SHADER, GstGL.GLSLVersion.NONE, GstGL.GLSLProfile.COMPATIBILITY | GstGL.GLSLProfile.ES, VERTEX_SHADER_SRC) self.shader = GstGL.GLShader.new(self.glcontext) self.shader.compile_attach_stage(vert_stage) self.shader.compile_attach_stage(frag_stage) self.shader.link() self.u_transformation = glGetUniformLocation.wrappedOperation( self.shader.get_program_handle(), 'u_transformation') a_position = self.shader.get_attribute_location('a_position') a_texcoord = self.shader.get_attribute_location('a_texcoord') self.vao = glGenVertexArrays(1) glBindVertexArray(self.vao) self.positions_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(POSITIONS), POSITIONS, GL_STATIC_DRAW) self.texcoords_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(TEXCOORDS), TEXCOORDS, GL_STATIC_DRAW) self.vbo_indices = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vbo_indices) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(INDICES), INDICES, GL_STATIC_DRAW) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices) glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer) glVertexAttribPointer.wrappedOperation(a_position, 2, GL_FLOAT, GL_FALSE, 0, None) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer) glVertexAttribPointer.wrappedOperation(a_texcoord, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(a_position) glEnableVertexAttribArray(a_texcoord) glBindVertexArray(0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindBuffer(GL_ARRAY_BUFFER, 0)
def __setitem__( self, slice, array): """Set slice of data on the array and vbo (if copied already) slice -- the Python slice object determining how the data should be copied into the vbo/array array -- something array-compatible that will be used as the source of the data, note that the data-format will have to be the same as the internal data-array to work properly, if not, the amount of data copied will be wrong. This is a reasonably complex operation, it has to have all sorts of state-aware changes to correctly map the source into the low-level OpenGL view of the buffer (which is just bytes as far as the GL is concerned). """ if slice.step and not slice.step == 1: raise NotImplemented( """Don't know how to map stepped arrays yet""" ) # TODO: handle e.g. mapping character data into an integer data-set data = ArrayDatatype.asArray( array ) data_length = ArrayDatatype.arrayByteCount( array ) start = (slice.start or 0) stop = (slice.stop or len(self.data)) if start < 0: start += len(self.data) start = max((start,0)) if stop < 0: stop += len(self.data) stop = max((stop,0)) self.data[ slice ] = data if self.copied and self.buffers: if start-stop == len(self.data): # re-copy the whole data-set self.copied = False elif len(data): # now the fun part, we need to make the array match the # structure of the array we're going to copy into and make # the "size" parameter match the value we're going to copy in, # note that a 2D array (rather than a 1D array) may require # multiple mappings to copy into the memory area... # find the step size from the dimensions and base size... size = ArrayDatatype.arrayByteCount( self.data[0] ) #baseSize = ArrayDatatype.unitSize( data ) # now create the start and distance values... start *= size stop *= size # wait until the last moment (bind) to copy the data... self._copy_segments.append( (start,(stop-start), data) )
def __setitem__( self, slice, array): """Set slice of data on the array and vbo (if copied already) slice -- the Python slice object determining how the data should be copied into the vbo/array array -- something array-compatible that will be used as the source of the data, note that the data-format will have to be the same as the internal data-array to work properly, if not, the amount of data copied will be wrong. This is a reasonably complex operation, it has to have all sorts of state-aware changes to correctly map the source into the low-level OpenGL view of the buffer (which is just bytes as far as the GL is concerned). """ if slice.step and not slice.step == 1: raise NotImplemented( """Don't know how to map stepped arrays yet""" ) # TODO: handle e.g. mapping character data into an integer data-set data = ArrayDatatype.asArray( array ) data_length = ArrayDatatype.arrayByteCount( array ) start = (slice.start or 0) stop = (slice.stop or len(self.data)) if start < 0: start += len(self.data) start = max((start,0)) if stop < 0: stop += len(self.data) stop = max((stop,0)) self.data[ slice ] = data if self.copied and self.buffers: if start-stop == len(self.data): # re-copy the whole data-set self.copied = False elif len(data): # now the fun part, we need to make the array match the # structure of the array we're going to copy into and make # the "size" parameter match the value we're going to copy in, # note that a 2D array (rather than a 1D array) may require # multiple mappings to copy into the memory area... # find the step size from the dimensions and base size... size = ArrayDatatype.arrayByteCount( self.data[0] ) #baseSize = ArrayDatatype.unitSize( data ) # now create the start and distance values... start *= size stop *= size # wait until the last moment (bind) to copy the data... self._copy_segments.append( (start,(stop-start), data) )
def copy_data( self ): """Copy our data into the buffer on the GL side (if required) Ensures that the GL's version of the data in the VBO matches our internal view of the data, either by copying the entire data-set over with glBufferData or by updating the already-transferred data with glBufferSubData. """ assert self.buffers, """Should do create_buffers before copy_data""" if self.copied: if self._copy_segments: while self._copy_segments: start,size,data = self._copy_segments.pop(0) dataptr = ArrayDatatype.voidDataPointer( data ) self.implementation.glBufferSubData(self.target, start, size, dataptr) else: if self.data is not None and self.size is None: self.size = ArrayDatatype.arrayByteCount( self.data ) self.implementation.glBufferData( self.target, self.size, self.data, self.usage, ) self.copied = True
def copy_data( self ): """Copy our data into the buffer on the GL side (if required) Ensures that the GL's version of the data in the VBO matches our internal view of the data, either by copying the entire data-set over with glBufferData or by updating the already-transferred data with glBufferSubData. """ assert self.buffers, """Should do create_buffers before copy_data""" if self.copied: if self._copy_segments: while self._copy_segments: start,size,data = self._copy_segments.pop(0) dataptr = ArrayDatatype.voidDataPointer( data ) self.implementation.glBufferSubData(self.target, start, size, dataptr) else: if self.data is not None and self.size is None: self.size = ArrayDatatype.arrayByteCount( self.data ) self.implementation.glBufferData( self.target, self.size, self.data, self.usage, ) self.copied = True
def set_array(self, data, size=None): """Update our entire array with new data""" self.data = data self.copied = False if size is not None: self.size = size elif self.data is not None: self.size = ArrayDatatype.arrayByteCount(self.data)
def set_array( self, data, size=None ): """Update our entire array with new data""" self.data = data self.copied = False if size is not None: self.size = size elif self.data is not None: self.size = ArrayDatatype.arrayByteCount( self.data )
def do_gl_start(self): frag_stage = GstGL.GLSLStage.new_default_fragment(self.context) vert_stage = GstGL.GLSLStage.new_with_string(self.context, GL_VERTEX_SHADER, GstGL.GLSLVersion.NONE, GstGL.GLSLProfile.COMPATIBILITY | GstGL.GLSLProfile.ES, VERTEX_SHADER) self.shader = GstGL.GLShader.new(self.context) self.shader.compile_attach_stage(vert_stage) self.shader.compile_attach_stage(frag_stage) self.shader.link() a_position = self.shader.get_attribute_location('a_position') a_texcoord = self.shader.get_attribute_location('a_texcoord') self.vao_id = glGenVertexArrays(1) glBindVertexArray(self.vao_id) self.positions_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(POSITIONS), POSITIONS, GL_STATIC_DRAW) self.texcoords_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(TEXCOORDS), TEXCOORDS, GL_STATIC_DRAW) self.vbo_indices_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vbo_indices_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(INDICES), INDICES, GL_STATIC_DRAW) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices_buffer); glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer); glVertexAttribPointer.wrappedOperation(a_position, 2, GL_FLOAT, GL_FALSE, 0, None) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer); glVertexAttribPointer.wrappedOperation(a_texcoord, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(a_position) glEnableVertexAttribArray(a_texcoord) glBindVertexArray(0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindBuffer(GL_ARRAY_BUFFER, 0) return True
def set_array( self, data, size=None ): """Update our entire array with new data data -- PyOpenGL-compatible array-data structure, numpy arrays, ctypes arrays, etc. size -- if not provided, will use arrayByteCount to determine the size of the data-array, thus this value (number of bytes) is required when using opaque data-structures, (such as ctypes pointers) as the array data-source. """ self.data = data self.copied = False if size is not None: self.size = size elif self.data is not None: self.size = ArrayDatatype.arrayByteCount( self.data )
def set_array( self, data, size=None ): """Update our entire array with new data data -- PyOpenGL-compatible array-data structure, numpy arrays, ctypes arrays, etc. size -- if not provided, will use arrayByteCount to determine the size of the data-array, thus this value (number of bytes) is required when using opaque data-structures, (such as ctypes pointers) as the array data-source. """ self.data = data self.copied = False if size is not None: self.size = size elif self.data is not None: self.size = ArrayDatatype.arrayByteCount( self.data )
def copy_data( self ): """Copy our data into the buffer on the GL side""" assert self.buffers, """Should do create_buffers before copy_data""" if self.copied: if self._copy_segments: while self._copy_segments: start,size,data = self._copy_segments.pop(0) dataptr = ArrayDatatype.voidDataPointer( data ) self.implementation.glBufferSubData(self.target, start, size, dataptr) else: if self.data is not None and self.size is None: self.size = ArrayDatatype.arrayByteCount( self.data ) self.implementation.glBufferData( self.target, self.size, self.data, self.usage, ) self.copied = True
def copy_data(self): """Copy our data into the buffer on the GL side""" assert self.buffers, """Should do create_buffers before copy_data""" if self.copied: if self._copy_segments: while self._copy_segments: start, size, data = self._copy_segments.pop(0) dataptr = ArrayDatatype.voidDataPointer(data) self.implementation.glBufferSubData( self.target, start, size, dataptr) else: if self.data is not None and self.size is None: self.size = ArrayDatatype.arrayByteCount(self.data) self.implementation.glBufferData( self.target, self.size, self.data, self.usage, ) self.copied = True
def arrayByteCount(self, value): return ArrayDatatype.arrayByteCount(value.data)
def arrayByteCount( self, value ): return ArrayDatatype.arrayByteCount( value.data )
def initializeGL(self): self.initGeometry() self.vertex_code = """ #version 120 //attribute vec4 color; attribute float x_position; attribute float y_position; //varying vec4 v_color; void main() { gl_Position = vec4(x_position, y_position, 0.0, 1.0); //v_color = color; } """ self.fragment_code = """ #version 120 //varying vec4 v_color; void main() { //gl_FragColor = v_color; gl_FragColor = vec4(1,1,1,1); } """ ## Build and activate program # Request program and shader slots from GPU self.program = GL.glCreateProgram() self.vertex = GL.glCreateShader(GL.GL_VERTEX_SHADER) self.fragment = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) # Set shaders source GL.glShaderSource(self.vertex, self.vertex_code) GL.glShaderSource(self.fragment, self.fragment_code) # Compile shaders GL.glCompileShader(self.vertex) GL.glCompileShader(self.fragment) # Attach shader objects to the program GL.glAttachShader(self.program, self.vertex) GL.glAttachShader(self.program, self.fragment) #GL.glBindAttribLocation(self.program, 0, "x_position1".encode('utf-8')) #GL.glBindAttribLocation(self.program, 1, "y_position1".encode('utf-8')) # Build program GL.glLinkProgram(self.program) # Get rid of shaders (not needed anymore) GL.glDetachShader(self.program, self.vertex) GL.glDetachShader(self.program, self.fragment) # Make program the default program GL.glUseProgram(self.program) # Create array object self.vao = GL.glGenVertexArrays(1) GL.glBindVertexArray(self.vao) # Request buffer slot from GPU self.x_data_buffer = GL.glGenBuffers(1) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.x), self.x, GL.GL_DYNAMIC_DRAW) self.y_data_buffer = GL.glGenBuffers(1) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) GL.glBufferData(GL.GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(self.y), self.y, GL.GL_DYNAMIC_DRAW) ## Bind attributes #self.stride = self.x.strides[0] #self.offset = ctypes.c_void_p(0) self.loc = GL.glGetAttribLocation(self.program, "x_position".encode('utf-8')) print(self.loc) GL.glEnableVertexAttribArray(self.loc) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.x_data_buffer) GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0) #self.stride = self.y.strides[0] #self.offset = ctypes.c_void_p(0) self.loc = GL.glGetAttribLocation(self.program, "y_position".encode('utf-8')) print(self.loc) GL.glEnableVertexAttribArray(self.loc) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.y_data_buffer) GL.glVertexAttribPointer(self.loc, 1, GL.GL_FLOAT, GL.GL_FALSE, 0, 0)
def init_gl(self, glcontext): #TODO deinit at some point assert not self.glcontext vert_stage = GstGL.GLSLStage.new_default_vertex(glcontext) frag_stage = GstGL.GLSLStage.new_with_string( glcontext, GL_FRAGMENT_SHADER, GstGL.GLSLVersion.NONE, GstGL.GLSLProfile.COMPATIBILITY | GstGL.GLSLProfile.ES, FRAGMENT_SHADER_SRC) self.hm_shader = GstGL.GLShader.new(glcontext) self.hm_shader.compile_attach_stage(vert_stage) self.hm_shader.compile_attach_stage(frag_stage) self.hm_shader.link() self.default_shader = GstGL.GLShader.new_default(glcontext) a_position = self.default_shader.get_attribute_location('a_position') a_texcoord = self.default_shader.get_attribute_location('a_texcoord') self.vao_id = glGenVertexArrays(1) glBindVertexArray(self.vao_id) self.positions_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(POSITIONS), POSITIONS, GL_STATIC_DRAW) self.texcoords_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(TEXCOORDS), TEXCOORDS, GL_STATIC_DRAW) self.vbo_indices_buffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vbo_indices_buffer) glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(INDICES), INDICES, GL_STATIC_DRAW) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices_buffer) glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer) glVertexAttribPointer.baseFunction(a_position, 2, GL_FLOAT, GL_FALSE, 0, None) glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer) glVertexAttribPointer.baseFunction(a_texcoord, 2, GL_FLOAT, GL_FALSE, 0, None) glEnableVertexAttribArray(a_position) glEnableVertexAttribArray(a_texcoord) glBindVertexArray(0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindBuffer(GL_ARRAY_BUFFER, 0) hm_w, hm_h = self.get_heatmap_texture_size() texture_ids = glGenTextures(1) self.hm_tex_id = texture_ids glActiveTexture(GL_TEXTURE0 + 1) glBindTexture(GL_TEXTURE_2D, self.hm_tex_id) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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) glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, hm_w, hm_h, 0, GL_RGBA, GL_FLOAT, None) self.glcontext = glcontext