def __init__(self): self.fbo = gl.GLuint(0) self.rendered_texture = gl.GLuint(0) self.depthrenderbuffer = gl.GLuint(0) self.pickingbuffer = gl.GLuint(0) self.vertex_buffer = gl.GLuint(0) self.program = GlProgram(shaders.vertex_copy, shaders.fragment_copy) gl.glGenBuffers(1, pointer(self.vertex_buffer)) data = (gl.GLfloat * 16)(-1, -1, 0, 0, - 1, 1, 0, 1, 1, 1, 1, 1, 1, -1, 1, 0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, sizeof(data), data, gl.GL_STATIC_DRAW) gl.glGenFramebuffers(1, pointer(self.fbo)) if not self.fbo: logging.error('failed fbo') gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self.fbo) gl.glGenTextures(1, pointer(self.rendered_texture)) if not self.rendered_texture: logging.error('failed rendered_texture') gl.glGenRenderbuffers(1, pointer(self.depthrenderbuffer)) gl.glGenRenderbuffers(1, pointer(self.pickingbuffer)) self.resize(1, 1)
def render_to_texture(): # select the target to draw into gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, framebuffer) draw_buffers = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glDrawBuffers(1, draw_buffers) gl.glViewport(0, 0, FB_WIDTH, FB_HEIGHT) # clear the destination gl.glClearColor(0.5, 0.6, 0.7, 1.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # prepare the rendering gl.glUseProgram(render_program) # send the vertex data data = (COLOR_VERTEX * 3)(((-0.6, -0.5), (1.0, 0.0, 0.0, 1.0)), ((0.6, -0.5), (0.0, 1.0, 0.0, 1.0)), ((0.0, 0.5), (0.0, 0.0, 1.0, 1.0))) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, render_vertexbuffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data), data, gl.GL_DYNAMIC_DRAW) # draw using the vertex array for vertex information gl.glBindVertexArray(render_vao) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3) gl.glBindVertexArray(0)
def create_ellipse(width, height, color): """ This creates an ellipse vertex buffer object (VBO). It can later be drawn with ``render_ellipse_filled``. This method of drawing an ellipse is much faster than calling ``draw_ellipse_filled`` each frame. """ num_segments = 64 data = [] for i in range(num_segments + 1): theta = 2.0 * 3.1415926 * i / num_segments x = width * math.cos(theta) y = height * math.sin(theta) data.extend([x, y]) vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) v2f = data data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(v2f)//2, width, height, color) return shape
def copy_texture_to_screen(): # select the target to draw into gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) gl.glViewport(0, 0, window.width, window.height) # clear the destination gl.glClearColor(0.4, 0.4, 0.4, 1.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) # select the program for drawing gl.glUseProgram(copy_program) # send the vertex data data = (TEXTURE_VERTEX * 8)(((-0.9, -0.9), (0.0, 0.0)), ((0.5, -0.9), (1.0, 0.0)), ((0.5, 0.5), (1.0, 1.0)), ((-0.9, 0.5), (0.0, 1.0)), ((0.6, 0.6), (0.0, 1.0)), ((1.0, 0.6), (1.0, 1.0)), ((1.0, 1.0), (1.0, 0.0)), ((0.6, 1.0), (0.0, 0.0)), ) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, copy_vertexbuffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data), data, gl.GL_DYNAMIC_DRAW) # draw gl.glBindVertexArray(copy_vao) gl.glDrawArrays(gl.GL_QUADS, 0, 8) gl.glBindVertexArray(0)
def __setitem__(self, key, value): with self.bound: sz = len(self) if isinstance(key, slice): start = int(key.start) if key.start is not None else 0 stop = int(key.stop) if key.stop is not None else start + value.size else: start = int(key) stop = start + 1 if start < 0 or stop < 0 or start >= stop: raise IndexError if stop > sz: newsz = max(sz * 2, stop) a = numpy.empty((newsz,), dtype=self.dtype) # intel dies when querying an empty buffer :[ if sz > 0: gl.glGetBufferSubData(gl.GL_ARRAY_BUFFER, 0, sz * self.dtype.itemsize, a.ctypes.data) b = numpy.asarray(value).reshape(-1) a[start:stop] = b gl.glBufferData(gl.GL_ARRAY_BUFFER, newsz * self.dtype.itemsize, a.ctypes.data, self.usage) else: a = numpy.ascontiguousarray(value, self.dtype).reshape(-1) sz = min((stop - start), len(a)) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, start * self.dtype.itemsize, sz * self.dtype.itemsize, a.ctypes.data)
def draw(self): ''' Draw the windows. ''' self.program.use() data = list(self.root.get_data(0, 0)) data = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, sizeof(data), data, gl.GL_DYNAMIC_DRAW) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_2D, self.texture) if self.textmanager.dirty: # only upload the texture to the GPU if it has actually changed gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, # level gl.GL_R8, self.textmanager.width, self.textmanager.height, 0, gl.GL_RED, gl.GL_UNSIGNED_BYTE, ctypes.create_string_buffer(self.textmanager.img.tobytes())) self.textmanager.dirty = False self.program.uniform1i(b"tex", 0) # set to 0 because the texture is bound to GL_TEXTURE0 self.program.vertex_attrib_pointer(self.buffer, b"position", 4) # self.program.vertex_attrib_pointer(self.buffer, b"texcoord", 2, stride=4 * sizeof(gl.GLfloat), offset=2 * sizeof(gl.GLfloat)) gl.glDrawArrays(gl.GL_QUADS, 0, len(data) // 4)
def set_vertex_attrib(self, name, data): ''' this is an ugly way to set vertex attribute data in a shader. lacks the flexibility of setting several attributes in one vertex buffer. name: the attribute name in the shader. data: a list of vertex attributes (positions, colors, texcoords, normals,...) example: name = 'positions' data = [(1, 1, 0), (2, 2, 1), ...] the items in data must all be 1D lists(or tuples) of the same length. ''' data_flatten = [x for vertex in data for x in vertex] size = len(data[0]) data_ctype = (gl.GLfloat * len(data_flatten))(*data_flatten) vbo_id = gl.GLuint(0) gl.glGenBuffers(1, ct.byref(vbo_id)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_ctype), data_ctype, gl.GL_STATIC_DRAW) location = gl.glGetAttribLocation(self.program, name.encode('ascii')) gl.glEnableVertexAttribArray(location) gl.glVertexAttribPointer(location, size, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) return vbo_id
def _set_vbo(vbo_id, points): """ Given a vertex buffer id, this sets the vertexes to be part of that buffer. """ data2 = (GL.GLfloat * len(points))(*points) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW)
def reserve(self, length, target=None): """ Fill the buffers with "length" zeroed elements. Parameters: length: Number of element the buffer will be able to hold """ if target is None: target = self.target self.bind() glBufferData(target, sizeof(self.format.struct)*length, c_void_p(0), self._usage)
def __init__(self, data: bytes, usage: str = 'static'): self.buffer_id = buffer_id = gl.GLuint() self.size = len(data) gl.glGenBuffers(1, byref(self.buffer_id)) if self.buffer_id.value == 0: raise ShaderException("Cannot create Buffer object.") gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffer_id) self.usage = Buffer.usages[usage] gl.glBufferData(gl.GL_ARRAY_BUFFER, self.size, data, self.usage) weakref.finalize(self, Buffer.release, buffer_id)
def _set_vbo(vbo_id: gl.GLuint, points: List[float]): """ Given a vertex buffer id, this sets the vertexes to be part of that buffer. """ # todo what does it do? data2 = (gl.GLfloat*len(points))(*points) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW)
def __init__(self, buffer, data_type=GLuint): # TODO Make so you don't have to initialize with a buffer. super().__init__() count = len(buffer) size = count * sizeof(data_type) Array = data_type * count glGenBuffers(1, self) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self) glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, Array(*buffer), GL_STATIC_DRAW) self.count = count self.size = size
def create_vbo_for_rects(v2f): vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(v2f)//2) return shape
def __init__(self, **args): super().__init__(**args) # create vertex array object self.vao = gl.GLuint(0) gl.glGenVertexArrays(1, ctypes.byref(self.vao)) gl.glBindVertexArray(self.vao) # create vertex buffer object self.vbo = gl.GLuint(0) gl.glGenBuffers(1, ctypes.byref(self.vbo)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(vertex_positions)), (gl.GLfloat * len(vertex_positions))(*vertex_positions), gl.GL_STATIC_DRAW) gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glEnableVertexAttribArray(0) # create index buffer object self.ibo = gl.GLuint(0) gl.glGenBuffers(1, self.ibo) gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo) gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, ctypes.sizeof(gl.GLuint * len(indices)), (gl.GLuint * len(indices))(*indices), gl.GL_STATIC_DRAW) # create shader self.shader = shader.Shader("vert.glsl", "frag.glsl") self.shader_matrix_location = self.shader.find_uniform( b"matrix") # get the shader matrix uniform location self.shader.use() # create matrices self.mv_matrix = matrix.Matrix() # modelview self.p_matrix = matrix.Matrix() # projection self.x = 0 # temporary variable pyglet.clock.schedule_interval( self.update, 1.0 / 60) # call update function every 60th of a second
def on_draw(self): gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) STRIDE = 8 self.program.use() self.program.vertex_attrib_pointer(self.buffer, b'position', 4, stride=STRIDE * ctypes.sizeof(gl.GLfloat)) self.program.vertex_attrib_pointer(self.buffer, b'tex_coord', 4, stride=STRIDE * ctypes.sizeof(gl.GLfloat), offset=4 * ctypes.sizeof(gl.GLfloat)) nb_vertices = 6*40*40 data = self.dungeon_map.vertex_data() data = (gl.GLfloat * (STRIDE * nb_vertices))(*data) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data), data, gl.GL_DYNAMIC_DRAW) gl.glDrawArrays(gl.GL_TRIANGLES, 0, nb_vertices)
def reserve(self, length, target=None): """ Fill the buffers with "length" zeroed elements. Parameters: length: Number of element the buffer will be able to hold """ if target is None: target = self.target self.bind() glBufferData(target, sizeof(self.format.struct) * length, c_void_p(0), self._usage)
def gen_vertices(self): # Just make a cube for now self.vertices = (GLfloat * 108)(*[ -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0 ]) glGenVertexArrays(1, self.vao) glGenBuffers(1, self.vbo) glBindBuffer(GL_ARRAY_BUFFER, self.vbo) glBufferData(GL_ARRAY_BUFFER, sizeof(self.vertices), self.vertices, GL_STATIC_DRAW) glBindVertexArray(self.vao) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0) glEnableVertexAttribArray(0)
def _on_draw(self): gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) STRIDE = 8 self.program.use() self.program.vertex_attrib_pointer(self.buffer, b"position", 4, stride=STRIDE * ctypes.sizeof(gl.GLfloat)) self.program.vertex_attrib_pointer( self.buffer, b"color", 4, stride=STRIDE * ctypes.sizeof(gl.GLfloat), offset=4 * ctypes.sizeof(gl.GLfloat)) if self.terrain.dirty or not self._cached_terrain_data: data = (float(d) for (x, y, z, c, u, v, (r, g, b, a), lum) in self.terrain.vertex_data() for d in (x + u, y + v, z, 1, r * lum, g * lum, b * lum, a)) data = (gl.GLfloat * (STRIDE * self.terrain.nb_vertices()))(*data) self._cached_terrain_data = data else: data = self._cached_terrain_data gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data), data, gl.GL_DYNAMIC_DRAW) gl.glDrawArrays(gl.GL_TRIANGLES, 0, self.terrain.nb_vertices()) self.sprite_program.use() gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_2D, self.sprite_texture) self.sprite_program.uniform1i(b'tex', 0) x, y, cp = self.pointed utex = [0.0, 1.0 / 16, 1.0 / 16, 0.0] vtex = [0.0, 0.0, 1.0 / 16, 1.0 / 16] data = (float(d) for (x, y, z, c, u, v, (r, g, b, a), lum) in self.terrain.vertex_data_tile(x, y) for d in (x + u, y + v, z + 1.0 / 256, 1, utex[(c - cp) % 4], vtex[(c - cp) % 4], 0.0, 0.0)) data = (gl.GLfloat * (STRIDE * 6))(*data) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data), data, gl.GL_DYNAMIC_DRAW) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
def render_road(self): if self.initialized < 3: vertices = [] colors = [] def vert(a, b, c): for v in (a, b, c): vertices.append(v) for c in color: colors.append(c) color = (0.4, 0.8, 0.4, 1.0) vert(-PLAYFIELD, +PLAYFIELD, 0) vert(+PLAYFIELD, +PLAYFIELD, 0) vert(+PLAYFIELD, -PLAYFIELD, 0) vert(-PLAYFIELD, -PLAYFIELD, 0) color = (0.4, 0.9, 0.4, 1.0) k = PLAYFIELD / 20.0 for x in range(-20, 20, 2): for y in range(-20, 20, 2): vert(k * x + k, k * y + 0, 0) vert(k * x + 0, k * y + 0, 0) vert(k * x + 0, k * y + k, 0) vert(k * x + k, k * y + k, 0) for poly, col in self.road_poly: color = (col[0], col[1], col[2], 1) for p in poly: vert(p[0], p[1], 0) self.initialized += 1 gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl_vertices = (gl.GLfloat * len(vertices))(*vertices) gl.glBindBuffer(gl.GL_ARRAY_BUFFER_ARB, self.vertex_vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER_ARB, len(vertices) * 4, gl_vertices, gl.GL_STATIC_DRAW) gl_colors = (gl.GLfloat * len(colors))(*colors) gl.glBindBuffer(gl.GL_ARRAY_BUFFER_ARB, self.color_vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER_ARB, len(colors) * 4, gl_colors, gl.GL_STATIC_DRAW) self.numdraw = len(vertices) // 3 gl.glBindBuffer(gl.GL_ARRAY_BUFFER_ARB, self.vertex_vbo_id) gl.glVertexPointer(3, gl.GL_FLOAT, 0, 0) gl.glEnableClientState(gl.GL_COLOR_ARRAY) gl.glBindBuffer(gl.GL_ARRAY_BUFFER_ARB, self.color_vbo_id) gl.glColorPointer(4, gl.GL_FLOAT, 0, 0) gl.glDrawArrays(gl.GL_QUADS, 0, self.numdraw)
def _create_filled_with_colors(point_list, color_list, shape_mode): number_points = len(point_list) vertex_data = [] for point in point_list: vertex_data.append(point[0]) vertex_data.append(point[1]) color_data = [] for color in color_list: color_data.append(color[0] / 255.) color_data.append(color[1] / 255.) color_data.append(color[2] / 255.) if len(color) == 3: color_data.append(1.0) else: color_data.append(color[3] / 255.) vbo_vertex_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_vertex_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(vertex_data))(*vertex_data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_vertex_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) # Colors vbo_color_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_color_id)) gl_color_list = (gl.GLfloat * len(color_data))(*color_data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_color_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_color_list), gl_color_list, gl.GL_STATIC_DRAW) shape = VertexBuffer(vbo_vertex_id, number_points, shape_mode, vbo_color_id=vbo_color_id) return shape
def create_filled_rectangles_with_colors(point_list, color_list) -> VertexBuffer: """ This function creates multiple rectangle/quads using a vertex buffer object. Creating the rectangles, and then later drawing it with ``render`` is faster than calling ``draw_rectangle``. >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> point_list = [0, 0, 100, 0, 100, 100, 0, 100] >>> color_list = [0, 255, 0] >>> my_shape = arcade.create_filled_rectangles_with_colors(point_list, color_list) >>> my_shape_list = ShapeElementList() >>> my_shape_list.append(my_shape) >>> my_shape_list.draw() >>> arcade.finish_render() >>> arcade.quick_run(0.25) """ vbo_vertex_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_vertex_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. gl_point_list = (gl.GLfloat * len(point_list))(*point_list) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_vertex_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_point_list), gl_point_list, gl.GL_STATIC_DRAW) # Colors vbo_color_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_color_id)) gl_color_list = (gl.GLfloat * len(color_list))(*color_list) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_color_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_color_list), gl_color_list, gl.GL_STATIC_DRAW) shape_mode = gl.GL_QUADS shape = VertexBuffer(vbo_vertex_id, len(point_list) // 2, shape_mode, vbo_color_id=vbo_color_id) return shape
def create_line(start_x: float, start_y: float, end_x: float, end_y: float, color: Color, line_width: float = 1): """ Create a line to be rendered later. This works faster than draw_line because the vertexes are only loaded to the graphics card once, rather than each frame. :Example: >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> arcade.start_render() >>> line1 = arcade.create_line(0, 0, 100, 100, (255, 0, 0), 2) >>> arcade.render(line1) >>> arcade.finish_render() >>> arcade.quick_run(0.25) """ data = [start_x, start_y, end_x, end_y] # print(data) vbo_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) shape_mode = gl.GL_LINES shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode) shape.color = color shape.line_width = line_width return shape
def __init__(self, attribute_index, buffer, dimension, data_type=GLfloat): # TODO Make so you don't have to initialize with a buffer. super().__init__() count = len(buffer) size = count * sizeof(data_type) Array = data_type * count glGenBuffers(1, self) glBindBuffer(GL_ARRAY_BUFFER, self) glBufferData(GL_ARRAY_BUFFER, size, Array(*buffer), GL_STATIC_DRAW) self.count = count self.size = size self.attribute_index = attribute_index self.dimension = dimension self.data_type_constant = VBO.DATA_TYPE_CONSTANT[data_type]
def init(self, data, target=None): """ Fill the buffer data with "data". Data must be formatted using the parent buffer format. This calls glBufferData. To initialize a buffer without data (ie: only reserving space), use reserve(). This method is called when assiging values to the data field of a buffer. Ex: buffer.data = ( (1.0, 2.0, 3.0, 4.0), ) Parameters: data: Data to use to initialize the buffer. """ if target is None: target = self.target self.bind(target) cdata = self.format.pack(data) glBufferData(target, sizeof(cdata), ptr_array(cdata), self._usage)
def upload_vertices(asset: ModelAsset, gl_usage=GL_STATIC_DRAW): vertex_count = -1 data = [] for key in asset.attribute_data: value = asset.attribute_data[key] data.append(value) if vertex_count == -1: vertex_count = len(value[1]) // value[0] if vertex_count == -1: vertex_count = 0 vertex_data = combine_attributes(vertex_count, *data) # noinspection PyCallingNonCallable,PyTypeChecker vertex_data_gl = (GLfloat * len(vertex_data))(*vertex_data) glBindBuffer(GL_ARRAY_BUFFER, asset.vertex_buffer_id) vertex_buffer_size = sizeof(vertex_data_gl) glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_data_gl, gl_usage)
def __init__(self, data): count = len(data) buffer_type = c_uint * count buffer = buffer_type() buffer[:] = data handle = c_uint() glGenBuffers(1, handle) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle) glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(c_uint), buffer, GL_STATIC_DRAW) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) super(IndexedVBO, self).__init__(handle.value) self.data_type = GL_UNSIGNED_INT self.count = count self.dimension = 1
def create_rectangle(center_x: float, center_y: float, width: float, height: float, color: Color, border_width: float=0, tilt_angle: float=0, filled=True) -> VertexBuffer: """ This function creates a rectangle using a vertex buffer object. Creating the rectangle, and then later drawing it with ``render_rectangle`` is faster than calling ``draw_rectangle``. >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> my_rect = arcade.create_rectangle(200, 200, 50, 50, (0, 255, 0), 3, 45) >>> arcade.render(my_rect) >>> arcade.finish_render() >>> arcade.quick_run(0.25) """ data = get_rectangle_points(center_x, center_y, width, height, tilt_angle) # print(data) vbo_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) if filled: shape_mode = gl.GL_QUADS else: shape_mode = gl.GL_LINE_LOOP shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode) shape.color = color shape.line_width = border_width return shape
def orphan(self, size=-1, double: bool = False): """ Re-allocate the entire buffer memory. This can be used to resize a buffer or for re-specification (orphan the buffer to avoid blocking). If the current buffer is busy in redering operations it will be deallocated by OpenGL when completed. :param int size: New size of buffer. -1 will retain the current size. :param bool double: Is passed in with `True` the buffer size will be doubled """ if size > -1: self._size = size if double: self._size *= 2 gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._glo) gl.glBufferData(gl.GL_ARRAY_BUFFER, self._size, None, self._usage)
def create_lines_with_colors(point_list: PointList, color_list, line_width: float = 1) -> VertexBuffer: shape_mode = gl.GL_LINES number_points = len(point_list) vertex_data = [] for point in point_list: vertex_data.append(point[0]) vertex_data.append(point[1]) color_data = _fix_color_list(color_list) vbo_vertex_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_vertex_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(vertex_data))(*vertex_data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_vertex_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) # Colors vbo_color_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_color_id)) gl_color_list = (gl.GLfloat * len(color_data))(*color_data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_color_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_color_list), gl_color_list, gl.GL_STATIC_DRAW) shape = VertexBuffer(vbo_vertex_id, number_points, shape_mode, vbo_color_id=vbo_color_id) shape.line_width = line_width return shape
def create_rect(width, height, color): """ Create a vertex buffer for a rectangle. """ v2f = [-width / 2, -height / 2, width / 2, -height / 2, width / 2, height / 2, -width / 2, height / 2] vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(v2f)//2, width, height, color) return shape
def create_colors(rect_list): """ Create a vertex buffer for a set of rectangles. """ v2f = [] for shape in rect_list: for i in range(4): v2f.extend(shape.color) vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) return vbo_id
def update(self, visible: ChunkList): chunks = self.edge_chunks * self.edge_chunks num_chunks = len(visible) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.offsets) if num_chunks > chunks: self.edge_chunks += 1 print(f"Growing the chunk buffer to {self.edge_chunks}") chunks = self.edge_chunks * self.edge_chunks gl.glBufferData(gl.GL_ARRAY_BUFFER, 2 * chunks * sizeof(gl.GLfloat), None, gl.GL_DYNAMIC_DRAW) chunk_offsets = (gl.GLfloat * (chunks * 2))() for i, chunk in enumerate(visible): chunk_offsets[i * 2:i * 2 + 2] = chunk.x, chunk.y self.stored_chunks.append(chunk.id) gl.glBufferSubData(gl.GL_ARRAY_BUFFER, 0, sizeof(chunk_offsets), chunk_offsets) self.instances = num_chunks
def construct_index_buffer(): chunk_indices = (gl.GLuint * (num_quads_x * num_quads_y * 6))() for row in range(num_quads_y): for col in range(num_quads_x): current_quad = row * num_quads_x + col # Calculate the current block in the chunk. left_corner = current_quad + row # Add one extra column each time we need to go up a row. index = current_quad * 6 # Convert to array space. chunk_indices[index:index + 6] = ( # Quad lower right triangle. left_corner, left_corner + 1, left_corner + num_vertices_x + 1, # Quad upper right triangle. left_corner + num_vertices_x + 1, left_corner + num_vertices_x, left_corner ) gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, sizeof(chunk_indices), chunk_indices, gl.GL_STATIC_DRAW)
def __setup_data_buffer(self): data_ptr = ct.cast( np.ctypeslib.as_ctypes(self.__data), ct.POINTER(ct.c_float) ) self.__data_buffer = util.buffer() gl.glBindBuffer(gl.GL_TEXTURE_BUFFER, self.__data_buffer.value) gl.glBufferData(gl.GL_TEXTURE_BUFFER, ct.sizeof(ct.c_float)*self.__data.size, data_ptr, gl.GL_STATIC_DRAW) if self.__data_texture is None: self.__data_texture = util.texture() gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_BUFFER, self.__data_texture.value) gl.glTexBuffer(gl.GL_TEXTURE_BUFFER, gl.GL_R32F, self.__data_buffer.value) self.__data_altered = False
def send_mesh_data_to_gpu(self): # pass mesh data to gpu if not self.mesh_quad_count: return gl.glBindVertexArray(self.vao) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo) gl.glBufferData(gl.GL_ARRAY_BUFFER, # Orphaning ctypes.sizeof(gl.GLfloat * CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_LENGTH * 7), None, gl.GL_DYNAMIC_DRAW ) gl.glBufferSubData( gl.GL_ARRAY_BUFFER, 0, ctypes.sizeof(gl.GLfloat * len(self.mesh)), (gl.GLfloat * len(self.mesh)) (*self.mesh) ) gl.glBufferSubData( gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(self.mesh)), ctypes.sizeof(gl.GLfloat * len(self.translucent_mesh)), (gl.GLfloat * len(self.translucent_mesh)) (*self.translucent_mesh) ) if not self.world.options.INDIRECT_RENDERING: return self.draw_commands = [ # Index Count Instance Count Base Index Base Vertex Base Instance self.mesh_quad_count * 6, 1, 0, 0, 0, # Opaque mesh commands self.translucent_quad_count * 6, 1, 0, self.mesh_quad_count * 4, 0 # Translucent mesh commands ] gl.glBindBuffer(gl.GL_DRAW_INDIRECT_BUFFER, self.indirect_command_buffer) gl.glBufferSubData( gl.GL_DRAW_INDIRECT_BUFFER, 0, ctypes.sizeof(gl.GLuint * len(self.draw_commands)), (gl.GLuint * len(self.draw_commands)) (*self.draw_commands) )
def create_rectangle(center_x: float, center_y: float, width: float, height: float, color): """ This function creates a rectangle using a vertex buffer object. Creating the rectangle, and then later drawing it with ``render_rectangle`` is faster than calling ``draw_rectangle``. """ x1 = -width / 2 + center_x y1 = -height / 2 + center_y x2 = width / 2 + center_x y2 = -height / 2 + center_y x3 = width / 2 + center_x y3 = height / 2 + center_y x4 = -width / 2 + center_x y4 = height / 2 + center_y data = [x1, y1, x2, y2, x3, y3, x4, y4] vbo_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(data) // 2) shape.color = color return shape
def __init__(self, **args): super().__init__(**args) # create vertex array object self.vao = gl.GLuint(0) gl.glGenVertexArrays(1, ctypes.byref(self.vao)) gl.glBindVertexArray(self.vao) # create vertex buffer object self.vbo = gl.GLuint(0) gl.glGenBuffers(1, ctypes.byref(self.vbo)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(vertex_positions)), (gl.GLfloat * len(vertex_positions))(*vertex_positions), gl.GL_STATIC_DRAW) gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glEnableVertexAttribArray(0) # create index buffer object self.ibo = gl.GLuint(0) gl.glGenBuffers(1, self.ibo) gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo) gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, ctypes.sizeof(gl.GLuint * len(indices)), (gl.GLuint * len(indices))(*indices), gl.GL_STATIC_DRAW) # create shader self.shader = shader.Shader("vert.glsl", "frag.glsl") self.shader.use()
def render_to_texture(in_size, out_size, view_z=None): z0, z1 = (0, in_size[2]) if view_z == None else view_z vertices = (VERTEX * 6)(((-1, -1), (0, 0)), ((1, -1), (1, 0)), ((1, 1), (1, 1)), ((1, 1), (1, 1)), ((-1, 1), (0, 1)), ((-1, -1), (0, 0))) gl.glBindTexture(gl.GL_TEXTURE_3D, rendered_texture) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, framebuffer) draw_buffers = (gl.GLenum * 1)(gl.GL_COLOR_ATTACHMENT0) gl.glDrawBuffers(1, draw_buffers) gl.glViewport(0, 0, out_size[0], out_size[1]) gl.glUseProgram(render_program) loc_depth = gl.glGetUniformLocation(render_program, ctypes.create_string_buffer(b'depth')) loc_texelSize = gl.glGetUniformLocation( render_program, ctypes.create_string_buffer(b'texelSize')) gl.glUniform3f(loc_texelSize, 1 / in_size[0], 1 / in_size[1], 1 / in_size[2]) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, render_vertexbuffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(vertices), vertices, gl.GL_DYNAMIC_DRAW) gl.glBindVertexArray(render_vao) gl.glClearColor(0.0, 0.0, 0.0, 0.0) for z in range(out_size[2]): gl.glFramebufferTexture3D(gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0, gl.GL_TEXTURE_3D, rendered_texture, 0, z) fbs = gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) assert fbs == gl.GL_FRAMEBUFFER_COMPLETE, 'FramebufferStatus is {}'.format( fbs) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) gl.glUniform1f(loc_depth, (z0 + z * (z1 - z0)) / in_size[2] / out_size[2]) gl.glBindTexture(gl.GL_TEXTURE_3D, input_texture) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) if z % 10 == 0: gl.glFinish() print('\033[K{}/{}'.format(z, out_size[2] - 1), end='\r') gl.glFinish() gl.glBindVertexArray(0)
def create_rects(rect_list): """ Create a vertex buffer for a set of rectangles. """ v2f = [] for shape in rect_list: v2f.extend([-shape.width / 2, -shape.height / 2, shape.width / 2, -shape.height / 2, shape.width / 2, shape.height / 2, -shape.width / 2, shape.height / 2]) vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(v2f)//2) return shape
def set_vertex_attrib(self, name, data, size=2, stride=0, offset=0): """Set vertex attribute data in a shader, lacks the flexibility of setting several attributes in one vertex buffer. name: the attribute name in the shader. data: a list of vertex attributes (positions, colors, ...) example: name = 'positions', data = [0, 0, 0, 1, 1, 0, 1, 1]. """ data_ctype = (gl.GLfloat * len(data))(*data) vbo_id = gl.GLuint(0) gl.glGenBuffers(1, ct.byref(vbo_id)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_ctype), data_ctype, gl.GL_STATIC_DRAW) location = gl.glGetAttribLocation(self.program, name.encode('ascii')) gl.glEnableVertexAttribArray(location) gl.glVertexAttribPointer(location, size, gl.GL_FLOAT, gl.GL_FALSE, stride, ct.c_void_p(offset)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) return vbo_id
def create_filled_rectangles(point_list, color: Color) -> VertexBuffer: """ This function creates multiple rectangle/quads using a vertex buffer object. Creating the rectangles, and then later drawing it with ``render`` is faster than calling ``draw_rectangle``. >>> import arcade >>> arcade.open_window(800,600,"Drawing Example") >>> point_list = [0, 0, 100, 0, 100, 100, 0, 100] >>> my_rect = arcade.create_filled_rectangles(point_list, (0, 255, 0)) >>> arcade.render(my_rect) >>> arcade.finish_render() >>> arcade.quick_run(0.25) """ data = point_list # print(data) vbo_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. data2 = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, gl.GL_STATIC_DRAW) shape_mode = gl.GL_QUADS shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode) shape.color = color return shape
def create_filled_rectangles(point_list, colors) -> VertexBuffer: """ This function creates multiple rectangle/quads using a vertex buffer object. Creating the rectangles, and then later drawing it with ``render`` is faster than calling ``draw_rectangle``. """ data = point_list # print(data) vbo_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_id)) # Create a buffer with the data # This line of code is a bit strange. # (gl.GLfloat * len(data)) creates an array of GLfloats, one for each number # (*data) initalizes the list with the floats. *data turns the list into a # tuple. gl_point_list = (gl.GLfloat * len(data))(*data) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_id) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_point_list), gl_point_list, gl.GL_STATIC_DRAW) shape_mode = gl.GL_QUADS # Colors vbo_color_id = gl.GLuint() gl.glGenBuffers(1, ctypes.pointer(vbo_color_id)) gl_color_list = (gl.GLfloat * len(colors))(*colors) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_color_id); gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl_color_list), gl_color_list, gl.GL_STATIC_DRAW); shape = VertexBuffer(vbo_id, len(data) // 2, shape_mode, vbo_color_id) return shape
def __init__(self, size=0, dtype=numpy.float32, usage=gl.GL_DYNAMIC_DRAW): ''' size - how much storage to allocate for this buffer in advance (in items, not bytes) dtype - type of items in storage (float, float16, float32, int, etc.) usage - one of GL_{STREAM,STATIC,DYNAMIC}_{READ,COPY,DRAW} Description copied from OpenGL reference pages: The frequency of access may be one of these: STREAM The data store contents will be modified once and used at most a few times. STATIC The data store contents will be modified once and used many times. DYNAMIC The data store contents will be modified repeatedly and used many times. The nature of access may be one of these: DRAW The data store contents are modified by the application, and used as the source for GL drawing and image specification commands. READ The data store contents are modified by reading data from the GL, and used to return that data when queried by the application. COPY The data store contents are modified by reading data from the GL, and used as the source for GL drawing and image specification commands.''' self.usage = usage self.dtype = numpy.dtype(dtype) bufid = ctypes.c_uint(0) gl.glGenBuffers(1, ctypes.byref(bufid)) self.bufid = bufid self.bound = _GLBufferContext(self.bufid) if size > 0: with self.bound: gl.glBufferData(gl.GL_ARRAY_BUFFER, size * self.dtype.itemsize, None, self.usage)
def __init__(self, ctx, data: Optional[Any] = None, reserve: int = 0, usage: str = 'static'): """ :param Context ctx: The context this buffer belongs to :param Any data: The data this buffer should contain. It can be bytes or any object supporting the buffer protocol. :param int reserve: Create a buffer of a specific byte size :param str usage: A hit of this buffer is ``static`` or ``dynamic`` (can mostly be ignored) """ self._ctx = ctx self._glo = glo = gl.GLuint() self._size = -1 self._usage = Buffer._usages[usage] gl.glGenBuffers(1, byref(self._glo)) # print(f"glGenBuffers() -> {self._glo.value}") if self._glo.value == 0: raise RuntimeError("Cannot create Buffer object.") # print(f"glBindBuffer({self._glo.value})") gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._glo) # print(f"glBufferData(gl.GL_ARRAY_BUFFER, {self._size}, data, {self._usage})") if data is not None and len(data) > 0: self._size, data = data_to_ctypes(data) gl.glBufferData(gl.GL_ARRAY_BUFFER, self._size, data, self._usage) elif reserve > 0: self._size = reserve gl.glBufferData(gl.GL_ARRAY_BUFFER, self._size, None, self._usage) else: raise ValueError( "Buffer takes byte data or number of reserved bytes") self.ctx.stats.incr('buffer') weakref.finalize(self, Buffer.release, self.ctx, glo)
def create_rectangle(width, height, color): """ This function creates a rectangle using a vertex buffer object. Creating the rectangle, and then later drawing it with ``render_rectangle`` is faster than calling ``draw_rectangle``. """ data = [-width / 2, -height / 2, width / 2, -height / 2, width / 2, height / 2, -width / 2, height / 2] vbo_id = GL.GLuint() GL.glGenBuffers(1, ctypes.pointer(vbo_id)) v2f = data data2 = (GL.GLfloat*len(v2f))(*v2f) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo_id) GL.glBufferData(GL.GL_ARRAY_BUFFER, ctypes.sizeof(data2), data2, GL.GL_STATIC_DRAW) shape = VertexBuffer(vbo_id, len(v2f)//2, width, height, color) return shape
def _set_points(self, points, kind, tris): """Helper to set fill and line points""" from pyglet import gl if points is None: self._counts[kind] = 0 points = np.asarray(points, dtype=np.float32, order='C') assert points.ndim == 2 and points.shape[1] == 2 array_count = points.size // 2 if kind == 'line' else points.size if kind == 'fill': assert tris is not None tris = np.asarray(tris, dtype=np.uint32, order='C') assert tris.ndim == 1 and tris.size % 3 == 0 tris.shape = (-1, 3) assert (tris < len(points)).all() self._tris[kind] = tris del tris self._points[kind] = points del points gl.glUseProgram(self._program) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self._buffers[kind]['array']) gl.glBufferData(gl.GL_ARRAY_BUFFER, self._points[kind].size * 4, self._points[kind].tostring(), gl.GL_STATIC_DRAW) if kind == 'line': self._counts[kind] = array_count if kind == 'fill': self._counts[kind] = self._tris[kind].size gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self._buffers[kind]['index']) gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, self._tris[kind].size * 4, self._tris[kind].tostring(), gl.GL_STATIC_DRAW) gl.glUseProgram(0)
def __setup_geometry_buffer(self): data_buffer = ((ct.c_float*3)*36)() # {{{ vertex data for cube v0 = ( .5, .5, .5 ) v1 = ( -.5, .5, .5 ) v2 = ( -.5, -.5, .5 ) v3 = ( .5, -.5, .5 ) v4 = ( .5, .5, -.5 ) v5 = ( -.5, .5, -.5 ) v6 = ( -.5, -.5, -.5 ) v7 = ( .5, -.5, -.5 ) data_buffer[0:3] = (v4, v0, v7) data_buffer[3:6] = (v0, v3, v7) data_buffer[6:9] = (v0, v1, v2) data_buffer[9:12] = (v0, v2, v3) data_buffer[12:15] = (v5, v1, v0) data_buffer[15:18] = (v5, v0, v4) data_buffer[18:21] = (v3, v6, v7) data_buffer[21:24] = (v3, v2, v6) data_buffer[24:27] = (v2, v1, v6) data_buffer[27:30] = (v6, v1, v5) data_buffer[30:33] = (v4, v6, v5) data_buffer[33:36] = (v7, v6, v4) # }}} data_ptr = ct.cast(ct.pointer(data_buffer), ct.POINTER(ct.c_float)) # create GL buffer self.__geom_buffer = util.buffer() gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.__geom_buffer.value) gl.glBufferData(gl.GL_ARRAY_BUFFER, ct.sizeof(data_buffer), data_ptr, gl.GL_STATIC_DRAW) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
def send_mesh_data_to_gpu(self): # pass mesh data to gpu if not self.mesh_index_counter: return gl.glBindVertexArray(self.vao) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_position_vbo) gl.glBufferData( gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(self.mesh_vertex_positions)), (gl.GLfloat * len(self.mesh_vertex_positions))(*self.mesh_vertex_positions), gl.GL_STATIC_DRAW) gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glEnableVertexAttribArray(0) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.tex_coord_vbo) gl.glBufferData(gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(self.mesh_tex_coords)), (gl.GLfloat * len(self.mesh_tex_coords))(*self.mesh_tex_coords), gl.GL_STATIC_DRAW) gl.glVertexAttribPointer(1, 3, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glEnableVertexAttribArray(1) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.shading_values_vbo) gl.glBufferData( gl.GL_ARRAY_BUFFER, ctypes.sizeof(gl.GLfloat * len(self.mesh_shading_values)), (gl.GLfloat * len(self.mesh_shading_values))(*self.mesh_shading_values), gl.GL_STATIC_DRAW) gl.glVertexAttribPointer(2, 1, gl.GL_FLOAT, gl.GL_FALSE, 0, 0) gl.glEnableVertexAttribArray(2) gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.ibo) gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, ctypes.sizeof(gl.GLuint * self.mesh_indices_length), (gl.GLuint * self.mesh_indices_length)(*self.mesh_indices), gl.GL_STATIC_DRAW)
def _buffer_data(self): with self: gl.glBufferData(self.target, 4 * self.ndarray.size, vec(self.ndarray.ravel(), 'int'), gl.GL_STATIC_DRAW)
def generate(self): for buffer in ["vertex", "color", "normal", "texture_coords"]: self.buffers[buffer] = gl.GLuint(0) gl.glGenBuffers(1, self.buffers[buffer]) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.buffers[buffer]) gl.glBufferData(gl.GL_ARRAY_BUFFER, self.buffer_size, None, gl.GL_DYNAMIC_DRAW)