def draw(self, uniforms, entities, models, textures=(), lights=(), *args, **kwargs): glUseProgram(self) # PREPARE SHADER glUniformMatrix4fv( # ctypes.data_as must be here and not at initialization. self.uniforms[b'perspective'], 1, GL_TRUE, uniforms.get(b'perspective').ctypes.data_as(POINTER(GLfloat)) ) glUniformMatrix4fv( self.uniforms[b'view'], 1, GL_TRUE, uniforms.get(b'view').ctypes.data_as(POINTER(GLfloat)) ) for i, entity in enumerate(lights): glUniform3f(self.uniforms[b'light[' + bytes(str(i), 'utf-8') + b'].position'], *entity.location) glUniform3f(self.uniforms[b'light[' + bytes(str(i), 'utf-8') + b'].color'], *entity.color) glUniform1f(self.uniforms[b'light[' + bytes(str(i), 'utf-8') + b'].constant'], entity.attenuation[0]) glUniform1f(self.uniforms[b'light[' + bytes(str(i), 'utf-8') + b'].linear'], entity.attenuation[1]) glUniform1f(self.uniforms[b'light[' + bytes(str(i), 'utf-8') + b'].quadratic'], entity.attenuation[1]) # PREPARE MODELS for model_index, texture_mapping in self.entities.items(): model = models[model_index] model.enable() # PREPARE TEXTURES glActiveTexture(GL_TEXTURE0) glActiveTexture(GL_TEXTURE0 + 1) for texture_list, entity_list in texture_mapping.items(): if hasattr(texture_list, '__iter__'): glBindTexture(GL_TEXTURE_2D, textures[0]) glUniform1i(self.uniforms[b'diffuse_texture'], 0) glBindTexture(GL_TEXTURE_2D, textures[1]) glUniform1i(self.uniforms[b'specular_texture'], 1) # textures[0].enable(slot=0) # textures[1].enable(slot=1) else: textures[texture_list].enable(slot=0) glUniform1i(self.uniforms[b'diffuse_texture'], 0) # PREPARE ENTITIES for entity in entity_list: glUniformMatrix4fv( self.uniforms[b'transformation'], 1, GL_TRUE, entity.get_transformation_matrix().ctypes.data_as(POINTER(GLfloat)) ) model.draw() glBindBuffer(GL_ARRAY_BUFFER, 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindTexture(GL_TEXTURE_2D, 0) glDisableVertexAttribArray(0) glDisableVertexAttribArray(1) glDisableVertexAttribArray(2)
def draw(self, uniforms, text, quad, textures=(), *args, **kwargs): glUseProgram(self) glDisable(GL_DEPTH_TEST) quad.enable() glUniform3f(self.uniforms[b'color'], 0.3, 0.3, 0.5) glUniformMatrix3fv( self.uniforms[b'transformation'], 1, GL_TRUE, text.get_transformation_matrix_2D().ctypes.data_as(POINTER(GLfloat)) ) textures.enable(slot=0) glUniform1i(self.uniforms[b'font_atlas'], 0) quad.draw() glBindBuffer(GL_ARRAY_BUFFER, 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindTexture(GL_TEXTURE_2D, 0) glDisableVertexAttribArray(0) glEnable(GL_DEPTH_TEST)
def draw(self, uniforms, entities, models, *args, **kwargs): glUseProgram(self) glUniformMatrix4fv( self.uniforms[b'perspective'], 1, GL_TRUE, uniforms.get(b'perspective').ctypes.data_as(POINTER(GLfloat)) ) glUniformMatrix4fv( self.uniforms[b'view'], 1, GL_TRUE, uniforms.get(b'view').ctypes.data_as(POINTER(GLfloat)) ) for model_index, entity_list in entities.items(): model = models[model_index] model.enable() for entity in entity_list: glUniformMatrix4fv( self.uniforms[b'transformation'], 1, GL_TRUE, entity.get_transformation_matrix().ctypes.data_as(POINTER(GLfloat)) ) glUniform3f(self.uniforms[b'color'], *entity.color) model.draw() glBindBuffer(GL_ARRAY_BUFFER, 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glBindTexture(GL_TEXTURE_2D, 0) glDisableVertexAttribArray(0)
def draw(self, uniforms, entity, models, textures=(), color=(1.0, 1.0, 1.0), *args, **kwargs): glUseProgram(self) glDisable(GL_DEPTH_TEST) # Draw objects once as invisible to set stencil values. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) # Don't write any color values to color buffer. glStencilMask(0xFF) # Enable writing. model = models[entity.model] model.positions.enable() model.indices.enable() glUniformMatrix4fv( self.uniforms[b'perspective'], 1, GL_TRUE, uniforms.get(b'perspective').ctypes.data_as(POINTER(GLfloat)) ) glUniformMatrix4fv( self.uniforms[b'view'], 1, GL_TRUE, uniforms.get(b'view').ctypes.data_as(POINTER(GLfloat)) ) glUniform3f(self.uniforms[b'color'], *color) glUniformMatrix4fv( self.uniforms[b'transformation'], 1, GL_TRUE, entity.get_transformation_matrix().ctypes.data_as(POINTER(GLfloat)) ) model.draw() # Draw again with larger model. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) glStencilFunc(GL_NOTEQUAL, 1, 0xFF) # Update with 1's where the objects are rendered. glStencilMask(0x00) # Value that AND's the value written to buffer. 0x00 basically disables writing to stencil. glUniformMatrix4fv( self.uniforms[b'transformation'], 1, GL_TRUE, create_transformation_matrix( *entity.location, *entity.rotation, *(entity.scale + 0.05) ).ctypes.data_as(POINTER(GLfloat)) ) model.draw() glBindBuffer(GL_ARRAY_BUFFER, 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) glDisableVertexAttribArray(0) glEnable(GL_DEPTH_TEST) glStencilMask(0xFF)
def _render_view(self): gl.glClearBufferfv(gl.GL_COLOR, 0, (gl.GLfloat * 4)(0.25, 0.25, 0.25, 1)) if not self.view: return w, h, d = self.view.shape size = w, h window_size = self.get_size() ob = render_view(self) vm = make_view_matrix(window_size, size, self.zoom, self.offset) vm = (gl.GLfloat * 16)(*vm) gl.glViewport(0, 0, *window_size) self._update_border(self.view.shape) with self.border_vao, self.line_program: gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, vm) r, g, b, a = self.drawing.palette.colors[ 0] # Color 0 is currently hardcoded background gl.glUniform3f(1, r / 256, g / 256, b / 256) gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4) with self.vao, self.copy_program: # Draw the actual drawing with ob["color"]: gl.glEnable(gl.GL_BLEND) gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, (gl.GLfloat * 16)(*vm)) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) self._draw_mouse_cursor() with self.border_vao, self.line_program: gl.glUniform3f(1, 0., 0., 0.) gl.glLineWidth(1) gl.glDrawArrays(gl.GL_LINE_LOOP, 0, 4)
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 __set_uniforms(self): # projection matrix (proj) proj_loc = gl.glGetUniformLocation(self.__prog.value, "proj") proj_matrix = self.__proj_matrix() proj_matrix_ptr = ct.cast( \ ct.pointer(np.ctypeslib.as_ctypes(proj_matrix)), ct.POINTER(ct.c_float) ) gl.glUniformMatrix4fv(proj_loc, 1, gl.GL_TRUE, proj_matrix_ptr) # voxel spacing voxel_spacing_loc = gl.glGetUniformLocation(self.__prog.value, "voxel_spacing") gl.glUniform3f(voxel_spacing_loc, self.__voxel_spacing[0]*self.__downsample, self.__voxel_spacing[1]*self.__downsample, self.__voxel_spacing[2]*self.__downsample) # voxel size voxel_size_loc = gl.glGetUniformLocation(self.__prog.value, "voxel_size") gl.glUniform3f(voxel_size_loc, self.__voxel_size[0]*self.__downsample, self.__voxel_size[1]*self.__downsample, self.__voxel_size[2]*self.__downsample) # data; not technically a "uniform" but a texture data_loc = gl.glGetUniformLocation(self.__prog.value, "data") gl.glUniform1i(data_loc, 0) gl.glActiveTexture(gl.GL_TEXTURE0) gl.glBindTexture(gl.GL_TEXTURE_BUFFER, self.__data_texture.value) # dims dims_loc = gl.glGetUniformLocation(self.__prog.value, "dims") gl.glUniform3i(dims_loc, self.__data.shape[0]/self.__downsample, self.__data.shape[1]/self.__downsample, self.__data.shape[2]/self.__downsample) # global_opacity global_opacity_loc = gl.glGetUniformLocation(self.__prog.value, "global_opacity") gl.glUniform1f(global_opacity_loc, self.__opacity) # min value min_value_loc = gl.glGetUniformLocation(self.__prog.value, "min_value") gl.glUniform1f(min_value_loc, self.__min_value) # saturation value saturation_value_loc = gl.glGetUniformLocation(self.__prog.value, "saturation_value") gl.glUniform1f(saturation_value_loc, self.__saturation_value) # downsample downsample_loc = gl.glGetUniformLocation(self.__prog.value, "downsample") gl.glUniform1i(downsample_loc, self.__downsample)
def render_view(window): """ Render the current view to a texture. """ drawing = window.drawing view = window.view changed = False # Update the overlay with the current stroke overlay = view.overlay w, h, d = view.shape size = w, h overlay_texture = _get_overlay_texture(size) if overlay.dirty and overlay.lock.acquire(timeout=0.01): rect = overlay.dirty x0, y0, x1, y1 = rect.box() overlay_data = overlay.data[x0:x1, y0:y1].tobytes("F") gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) # Needed for writing 8bit data gl.glTextureSubImage2D(overlay_texture.name, 0, *rect.position, *rect.size, gl.GL_RGBA_INTEGER, gl.GL_UNSIGNED_BYTE, overlay_data) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4) overlay.dirty = None overlay.lock.release() changed = True # Update the image texture data = drawing.data drawing_texture = _get_3d_texture(data.shape) if drawing.dirty: with drawing.lock: update_data = data[drawing.dirty].tobytes(order="F") sx, sy, sz = drawing.dirty drawing.dirty = None sw = sx.stop - sx.start sh = sy.stop - sy.start sd = sz.stop - sz.start gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1) # Needed for writing 8bit data gl.glTextureSubImage3D(drawing_texture.name, 0, sx.start, sy.start, sz.start, sw, sh, sd, gl.GL_RED_INTEGER, gl.GL_UNSIGNED_BYTE, update_data) gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 4) changed = True # Render everything to the offscreen buffer # TODO we actually should not have to redraw the offscreen_buffer unless something has changed # (e.g. drawing, overlay, palette or cursor) offscreen_buffer = _get_offscreen_buffer(size) colors = _get_colors(drawing.palette.colors) vao = _get_vao() draw_program = _get_program() empty_texture = _get_empty_texture(size) cursor_pos = d - view.index - 1 # TODO why? other_layer_alpha = 0.3 if view.show_only_current_layer or view.layer_being_switched else 1.0 T = _get_transform(view.rotation) with vao, offscreen_buffer: gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glViewport(0, 0, w, h) gl.glClearBufferfv(gl.GL_COLOR, 0, EMPTY_COLOR) with draw_program, drawing_texture: gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, (gl.GLfloat * 16)(*T)) gl.glUniform3f(1, *view.direction) gl.glUniform4fv(5, 256, colors) # Draw the layers below the current one if cursor_pos < d - 1: with empty_texture: gl.glUniform1f(2, other_layer_alpha) gl.glUniform2i(3, cursor_pos + 1, d) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) # Draw the current layer + overlay with overlay_texture: gl.glUniform1f(2, 1) gl.glUniform2i(3, cursor_pos, cursor_pos + 1) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) # Draw the layers on top if cursor_pos > 0: with empty_texture: gl.glUniform1f(2, other_layer_alpha) gl.glUniform2i(3, 0, cursor_pos) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) return offscreen_buffer
def on_draw(self): # Prevent trying to draw before things have been set up if not hasattr(self, "offscreen_buffer"): return # Model matrix we'll use to position the main model suzanne_model_matrix = (Matrix4.new_identity().rotatex( -math.pi / 2).rotatez(time())) # Rotate over time plane_model_matrix = Matrix4.new_rotatey(math.pi).translate(0, 0, 2) # Render to an offscreen buffer with self.offscreen_buffer, self.view_program, \ enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE): gl.glDepthMask(gl.GL_TRUE) w, h = self.size aspect = h / w # Calculate a view frustum; this is basically our camera. near = 5 far = 15 width = 2 height = 2 * aspect frustum = (Matrix4.new(near / width, 0, 0, 0, 0, near / height, 0, 0, 0, 0, -(far + near) / (far - near), -1, 0, 0, -2 * far * near / (far - near), 0)) # The view matrix positions the camera in the scene view_matrix = (Matrix4.new_identity().translate(0, 0, -8)) # Send the matrices to GL gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, gl_matrix(frustum * view_matrix)) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(suzanne_model_matrix)) gl.glUniform4f(2, 0.3, 0.3, 1, 1) # Set the "color" uniform to blue self.suzanne.draw() # We'll also draw a simple plane behind the main model gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(plane_model_matrix)) gl.glUniform4f(2, 0.3, 1, 0.3, 1) # Set the "color" uniform to green self.plane.draw(mode=gl.GL_TRIANGLE_STRIP) # Render shadow buffer # Basically the same scene as above, but to a different buffer and from a different view with self.shadow_buffer, self.view_program, enabled( gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE): gl.glDepthMask(gl.GL_TRUE) frustum = Matrix4.new_perspective(1, 1, 1, 12) view_matrix = (Matrix4.new_identity().translate( 0, 0, -4).rotatey(0.5).rotatex(0.3)) light_pos = (view_matrix.inverse() * Point3(0, 0, 0)) light_view_matrix = frustum * view_matrix gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, gl_matrix(light_view_matrix)) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(suzanne_model_matrix)) gl.glUniform4f(2, 0.9, 0.3, 0.4, 1) self.suzanne.draw() gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(plane_model_matrix)) self.plane.draw(mode=gl.GL_TRIANGLE_STRIP) # Now draw the offscreen buffer to another buffer, combining it with the # lighting information to get a nice image. # Note: This step is pretty pointless here, as we might just draw directly to screen. # Just demonstrates how to do it. with self.vao, self.offscreen_buffer2, self.lighting_program, disabled( gl.GL_CULL_FACE, gl.GL_DEPTH_TEST): gl.glUniform3f(0, *light_pos) gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE, gl_matrix(light_view_matrix)) # Bind some of the offscreen buffer's textures so the shader can read them. with self.offscreen_buffer["color"], self.offscreen_buffer["normal"], \ self.offscreen_buffer["position"], self.shadow_buffer["depth"]: gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) # Now render the finished image to the screen with self.vao, self.copy_program, disabled(gl.GL_CULL_FACE, gl.GL_DEPTH_TEST): with self.offscreen_buffer2["color"]: gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
def on_draw(self): gl.glClearBufferfv(gl.GL_COLOR, 0, BG_COLOR) if self.drawing: window_size = self.get_pixel_aligned_size() w, h = self.drawing.size vm = (gl.GLfloat * 16)(*make_view_matrix( window_size, self.drawing.size, self.zoom, self.offset)) offscreen_buffer = render_drawing(self.drawing, self.highlighted_layer) ww, wh = window_size gl.glViewport(0, 0, int(ww), int(wh)) # Draw a background rectangle with self.vao, self.copy_program: gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, (gl.GLfloat * 16)(*vm)) if self.drawing and self.drawing.grid: with self.get_background_texture( self.drawing.palette.colors[0], 0.9): gw, gh = self.drawing.grid_size gl.glUniform2f(1, w / (gw * 2), h / (gh * 2)) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) else: #gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) # r, g, b, _ = self.drawing.palette.get_color_as_float(self.drawing.palette.colors[0]) # gl.glClearColor(r, g, b, 1) # TODO should fill with color 0 here! # gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) with self.get_background_texture( self.drawing.palette.colors[0], 1): gw, gh = self.drawing.grid_size gl.glUniform2f(1, w / (gw * 2), h / (gh * 2)) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) with offscreen_buffer["color"]: gl.glUniform2f(1, 1, 1) gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_ONE, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, vm) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) with self.line_program: with self.border_vao: self.update_border(self.drawing.current.rect) gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, vm) # r, g, b, _ = self.drawing.palette.get_color_as_float(self.drawing.palette.colors[0]) # gl.glUniform3f(1, r, g, b) # gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, 4) gl.glUniform3f(1, 0., 0., 0.) gl.glLineWidth(1) gl.glDrawArrays(gl.GL_LINE_LOOP, 0, 4) # Selection rectangle if self.stroke: tool = self.stroke.tool selection = ((tool and tool.show_rect and tool.rect) or self.selection) if selection: self.set_selection(selection) with self.selection_vao: gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE, vm) gl.glUniform3f(1, 1., 1., 0.) gl.glLineWidth(1) gl.glDrawArrays(gl.GL_LINE_LOOP, 0, 4) if not self.tablet.active: self._draw_mouse_cursor() ui.draw_ui(self) gl.glFinish( ) # No double buffering, to minimize latency (does this work?)
def __init__(self): #consider bumping opengl version if apple supports it #amdgpu-mesa currently supports up to 4.5 super(ControledRender, self).__init__(512, 512, fullscreen=False, config=gl.Config(major_version=4, minor_version=1), visible=False) print(self.context.get_info().get_version()) self.vertex_buffer = gl.GLuint(0) self.vao = gl.GLuint(0) #self.prev_program = (gl.GLint * 1)() self.setupFBOandTextures() self.setupShaders() data = [ -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0 ] dataGl = (gl.GLfloat * len(data))(*data) gl.glGenBuffers(1, ctypes.byref(self.vertex_buffer)) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer) gl.glBufferData(gl.GL_ARRAY_BUFFER, len(dataGl) * 4, dataGl, gl.GL_STATIC_DRAW) gl.glGenVertexArrays(1, ctypes.byref(self.vao)) gl.glBindVertexArray(self.vao) gl.glUseProgram(self.programA) self.pos_posA = gl.glGetAttribLocation( self.programA, ctypes.create_string_buffer(b"a_position")) assert (self.pos_posA >= 0) gl.glEnableVertexAttribArray(self.pos_posA) gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertex_buffer) gl.glVertexAttribPointer(self.pos_posA, 2, gl.GL_FLOAT, False, 0, 0) if args["shape"] == "sphere": self.radius_pos = gl.glGetUniformLocation( self.programA, b"radius") self.center_pos = gl.glGetUniformLocation( self.programA, b"center") self.checkUniformLocation(self.radius_pos) self.checkUniformLocation(self.center_pos) gl.glUniform1f(self.radius_pos, args["radius"]) gl.glUniform3f(self.center_pos, args["center"][0], args["center"][1], args["center"][2]) elif args["shape"] == "cylinder": self.radius_pos = gl.glGetUniformLocation( self.programA, b"radius") self.height_pos = gl.glGetUniformLocation( self.programA, b"height") self.checkUniformLocation(self.radius_pos) self.checkUniformLocation(self.height_pos) gl.glUniform1f(self.radius_pos, args["radius"]) gl.glUniform1f(self.height_pos, args["height"]) self.slice_pos = gl.glGetUniformLocation(self.programA, b"slice") self.step_pos = gl.glGetUniformLocation(self.programA, b"step") self.checkUniformLocation(self.slice_pos) gl.glUniform1f(self.step_pos, 1 / args["resolution"]) #may need changed for nonsquare textures gl.glViewport(0, 0, args["resolution"], args["resolution"])