def __init__(self, size): """Initialize viewport with initial Face rotation and position.""" self.__size = size self.__height, self.__width = self.__size self.__output_image = zeros(self.__width * self.__height * 4, dtype='f') self.__light = None self.__face = None self.__model_matrix = zeros((4, 4), dtype='f') self.__light_matrix = zeros((4, 4), dtype='f') self.__init_display() self.__enable_depth_test() glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_VERTEX_ARRAY) glClearColor(1., 1., 1., 0.) self.__sh = ShadersHelper(['face.vert', 'depth.vert'], ['face.frag', 'depth.frag'], 1, 2) glutDisplayFunc(self.__display) self.__callback = None self.__sh.add_attribute(0, self.__mean_face, 'mean_position') self.__sh.bind_buffer() self.__sh.use_shaders() self.__sh.link_texture('principal_components', 0) self.__sh.link_texture('depth_map', 1) self.__bind_pca_texture() self.__sh.bind_depth_texture(self.__size)
def __init__(self, size): """Initialize viewport with initial Face rotation and position.""" self.__size = size self.__height, self.__width = self.__size self.__output_image = zeros(self.__width * self.__height * 4, dtype='f') self.__light = None self.__face = None self.__face_vertices = None self.__model_matrix = zeros((4, 4), dtype='f') self.__light_matrix = zeros((4, 4), dtype='f') self.__init_display() self.__enable_depth_test() glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_VERTEX_ARRAY) glClearColor(1., 1., 1., 0.) self.__sh = ShadersHelper(['face.vert', 'depth.vert'], ['face.frag', 'depth.frag'], 2, 1) glutDisplayFunc(self.__display) self.__callback = None self.__synchronous = False self.__sh.add_attribute(0, array([]), 'face_vertices') self.__sh.add_attribute(1, array([]), 'normal_vector') self.__sh.bind_buffer() self.__sh.use_shaders() self.__sh.link_texture('depth_map', 0) self.__sh.bind_depth_texture(self.__size)
def do_configure_event(self, event): ClientWindow.do_configure_event(self, event) drawable = self.glarea.get_gl_drawable() context = self.glarea.get_gl_context() self.yuv420_shader = None # Re-create textures self.current_mode = GLClientWindow.MODE_UNINITIALIZED if not drawable.gl_begin(context): raise Exception("** Cannot create OpenGL rendering context!") w, h = self.get_size() log("Configure widget size: %d x %d" % (w, h)) glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_FRAGMENT_PROGRAM_ARB) if self.textures is None: self.textures = glGenTextures(3) drawable.gl_end()
def Draw(self): """draw a curve of all previous data, up to a certain point (self.resolution)""" self.vbo.bind() self.vbo.copy_data() glEnableClientState(GL_VERTEX_ARRAY) glVertexPointer(2, GL_FLOAT, 0, self.vbo) if self.buffer_full: if self.previous_index != self.size - 1: glPushMatrix() glTranslatef(-1 * (self.previous_index + 1), 0.0, 0.0) glDrawArrays(GL_LINE_STRIP, (self.previous_index + 1), (self.size - self.previous_index - 1)) glPopMatrix() glPushMatrix() glTranslatef(self.size - self.previous_index - 1, 0.0, 0.0) glDrawArrays(GL_LINE_STRIP, 0, (self.previous_index + 1)) glPopMatrix() else: glDrawArrays(GL_LINE_STRIP, 0, (self.previous_index + 1)) glDisableClientState(GL_VERTEX_ARRAY) self.vbo.unbind()
class GLPixmapBacking(PixmapBacking): def __init__(self, wid, w, h, old_backing, mmap_enabled, mmap): Backing.__init__(self, wid, mmap_enabled, mmap) display_mode = (gtk.gdkgl.MODE_RGB | gtk.gdkgl.MODE_SINGLE) # We use single buffer because double doesn't work, figure out why try: self.glconfig = gtk.gdkgl.Config(mode=display_mode) except gtk.gdkgl.NoMatches, e: raise Exception("could not find matching mode for %s: %s" % (display_mode, e)) self._backing = gtk.gdkgl.ext(gdk.Pixmap(gdk.get_default_root_window(), w, h)) log.info("Creating GL pixmap size %d %d " % (w, h)) self.gldrawable = self._backing.set_gl_capability(self.glconfig) log.info("drawable ok") # Then create an indirect OpenGL rendering context. self.glcontext = gtk.gdkgl.Context(self.gldrawable, direct=True) log.info("context ok") if not self.glcontext: raise Exception("** Cannot create OpenGL rendering context!") log.info("OpenGL rendering context is created.") self.texture = None self.textures = [ 0 ] self.use_openGL_CSC = True self.yuv420_shader = None # OpenGL begin if not self.gldrawable.gl_begin(self.glcontext): return False glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glPixelStorei(GL_UNPACK_ALIGNMENT, 1) self.gldrawable.gl_end() cr = self._backing.cairo_create() if old_backing is not None and old_backing._backing is not None: # Really we should respect bit-gravity here but... meh. cr.set_operator(cairo.OPERATOR_SOURCE) cr.set_source_pixmap(old_backing._backing, 0, 0) cr.paint() old_w, old_h = old_backing._backing.get_size() cr.move_to(old_w, 0) cr.line_to(w, 0) cr.line_to(w, h) cr.line_to(0, h) cr.line_to(0, old_h) cr.line_to(old_w, old_h) cr.close_path() else: cr.rectangle(0, 0, w, h) cr.set_source_rgb(1, 1, 1) cr.fill()
def SetDisplayingItems(self, data, dataLen, colors): self.data = data self.colors = colors self.xcount = len(unique(data[:, 0])) self.ycount = len(unique(data[:, 1])) workingData = self.data workingColors = self.colors self.dataNum = dataLen self.colorsNum = self.dataNum maxVals = amax(workingData, axis=0) self.xMax = maxVals[0] self.yMax = maxVals[1] self.zMax = maxVals[2] minVals = amin(workingData, axis=0) self.xMin = minVals[0] self.yMin = minVals[1] self.zMin = minVals[2] # print "Max before offset:", self.xMax, self.yMax, self.zMax # print "Min before offset:", self.xMin, self.yMin, self.zMin self.diffX = (self.xMax + self.xMin) / 2 self.diffY = (self.yMax + self.yMin) / 2 self.diffZ = (self.zMax + self.zMin) / 2 # print "Offset:", self.diffX, self.diffY, self.diffZ workingData = subtract(workingData, array([self.diffX, self.diffY, self.diffZ], float32)) # recollect limitations maxVals = amax(workingData, axis=0) self.xMax = maxVals[0] self.yMax = maxVals[1] self.zMax = maxVals[2] minVals = amin(workingData, axis=0) self.xMin = minVals[0] self.yMin = minVals[1] self.zMin = minVals[2] # print "Max:", self.xMax, self.yMax, self.zMax # print "Min:", self.xMin, self.yMin, self.zMin self.eyeDistance = 100 * max(abs(self.xMax), abs(self.xMin), abs(self.yMax), abs(self.yMin), abs(self.zMax), abs(self.zMin)) # print "eye distance:", self.eyeDistance self.vertices_vbo = glGenBuffers(1) glEnableClientState(GL_VERTEX_ARRAY) glBindBuffer(GL_ARRAY_BUFFER, self.vertices_vbo) glBufferData(GL_ARRAY_BUFFER, workingData.nbytes, workingData, GL_STATIC_DRAW) glVertexPointer(3, GL_FLOAT, 0, None) glBindBuffer(GL_ARRAY_BUFFER, 0) self.colors_vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.colors_vbo) glBufferData(GL_ARRAY_BUFFER, workingColors.nbytes, workingColors, GL_STATIC_DRAW) glColorPointer(3, GL_FLOAT, 0, None) glBindBuffer(GL_ARRAY_BUFFER, 0) print "Points and color is ready"
def draw_circle_memoized(p, n, r, sides=64): """Draw circle given point, normal vector, radius, and # sides. Uses the function compute_circle to generate points. """ vertices, count = compute_circle(*p, *n, r, sides) # draw vertices glEnableClientState(GL_VERTEX_ARRAY) glVertexPointer(3, GL_FLOAT, 0, vertices) glDrawArrays(GL_LINE_STRIP, 0, count) glDisableClientState(GL_VERTEX_ARRAY)
def draw_helix_memoized(p, n, r, pitch=1, turns=1.0, sides=64): """Draw helix given point, normal vector, radius, pitch, # turns, and # sides. Uses the function compute_helix to generate points. """ vertices, count = compute_helix(*p, *n, r, pitch, turns, sides) # draw vertices glEnableClientState(GL_VERTEX_ARRAY) glVertexPointer(3, GL_FLOAT, 0, vertices) glDrawArrays(GL_LINE_STRIP, 0, count) glDisableClientState(GL_VERTEX_ARRAY)
def draw_detector(self): glUseProgram(self.shader) try: self.dom_positions_vbo.bind() try: glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(self.dom_positions_vbo) glPointSize(2) glDrawArrays(GL_POINTS, 0, len(self.dom_positions)*3) finally: self.dom_positions_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) finally: glUseProgram(0)
def Render(self, mode): """Render the geometry for the scene.""" shaders.glUseProgram(self.shader) try: self.vbo.bind() try: glEnableClientState(GL_VERTEX_ARRAY) GLVertexPointer(self.vbo) glDrawArrays(GL_TRIANGLES, 0, 9) finally: self.vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) finally: shaders.glUseProgram(0)
def draw_points(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glEnableClientState(GL_VERTEX_ARRAY) # glVertexPointer(3, GL_FLOAT, 24, points) # glColorPointer(3, GL_INT, 24, points+12) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 24, points) glEnableVertexAttribArray(0) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 24, points + 12) glEnableVertexAttribArray(1) glDrawArrays(GL_POINTS, 0, imgnp.shape[0] * imgnp.shape[1]) glDisableVertexAttribArray(0) glDisableVertexAttribArray(1) glutSwapBuffers()
def draw(self): glDisable(GL_LIGHTING) glLineWidth(self._width) glColor(*self._color) glEnableClientState(GL_VERTEX_ARRAY) if self._vbo: with self._vbo: glVertexPointerf(self._vbo) glDrawArrays(GL_LINE_STRIP, 0, len(self._vbo)) glDisableClientState(GL_VERTEX_ARRAY) glEnable(GL_LIGHTING)
def display(self): self.world.drawGL() glDisable(GL_LIGHTING) glLineWidth(2.0) glEnableClientState(GL_VERTEX_ARRAY) for (color, vbo) in self.trace_vbos: glColor(*color) with vbo: glVertexPointerf(vbo) glDrawArrays(GL_LINE_STRIP, 0, len(vbo)) glDisableClientState(GL_VERTEX_ARRAY) glEnable(GL_LIGHTING)
def paintGL(self): """ Drawing routing """ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() #Draw spiral in 'immediate mode' #WARNING: You should not be doing the spiral calculation inside the loop #even if you are using glBegin/glEnd, sin/cos are fairly expensive functions #For now left here to make code simpler radius = 1.0 x = radius * math.sin(0) y = radius * math.cos(0) glColor(0.0, 1.0, 0.0) glBegin(GL_LINE_STRIP) for deg in range(1000): glVertex(x, y, 0.0) rad = math.radians(deg) radius -= 0.001 x = radius * math.sin(rad) y = radius * math.cos(rad) glEnd() glEnableClientState(GL_VERTEX_ARRAY) #TODO: Use list comprehension spiral_array = [] #Second spiral using "array immediate mode" (i.e vertex arrays) radius = 0.8 x = radius * math.sin(0) y = radius * math.cos(0) glColor(1.0, 0.0, 0.0) for deg in range(820): spiral_array.append([x, y]) rad = math.radians(deg) radius -= 0.001 x = radius * math.sin(rad) y = radius * math.cos(rad) glVertexPointerf(spiral_array) glDrawArrays(GL_LINE_STRIP, 0, len(spiral_array)) glFlush()
def gl_init(self): drawable = self.gl_begin() w, h = self.size log("GL Pixmap backing size: %d x %d, drawable=%s", w, h, drawable) if not drawable: return None if not self.gl_setup: glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(0.0, w, h, 0.0, -1.0, 1.0) glMatrixMode(GL_MODELVIEW) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_FRAGMENT_PROGRAM_ARB) if self.textures is None: self.textures = glGenTextures(3) self.gl_setup = True return drawable
def draw_lines(ls): glDisableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_VERTEX_ARRAY) glLineWidth(3.0) allpts = ls.v[ls.e.flatten()].astype(np.float32) glVertexPointerf(allpts) if hasattr(ls, 'vc') or hasattr(ls, 'ec'): glEnableClientState(GL_COLOR_ARRAY) if hasattr(ls, 'vc'): glColorPointerf(ls.vc[ls.e.flatten()].astype(np.float32)) else: clrs = np.ones( (ls.e.shape[0] * 2, 3)) * np.repeat(ls.ec, 2, axis=0) glColorPointerf(clrs) else: glDisableClientState(GL_COLOR_ARRAY) glDisable(GL_LIGHTING) glDrawElementsui(GL_LINES, np.arange(len(allpts), dtype=np.uint32))
def draw_circle_trig(p, n, r, sides=36): """Draw circle given point, normal vector, radius, and # sides.""" a, b, n = rotate_basis(*n) tau = 6.28318530717958647692 count = sides + 1 vertices = np.empty(count * 3) for i in range(count): vertices[i * 3] = p[0] + r * (a[0] * math.cos(i * tau / sides) + b[0] * math.sin(i * tau / sides)) vertices[i * 3 + 1] = p[1] + r * (a[1] * math.cos(i * tau / sides) + b[1] * math.sin(i * tau / sides)) vertices[i * 3 + 2] = p[2] + r * (a[2] * math.cos(i * tau / sides) + b[2] * math.sin(i * tau / sides)) # draw vertices glEnableClientState(GL_VERTEX_ARRAY) glVertexPointer(3, GL_FLOAT, 0, vertices) glDrawArrays(GL_LINE_STRIP, 0, count) glDisableClientState(GL_VERTEX_ARRAY)
def paint(self): """ For all of the known terrain, render whatever faces are exposed. """ if self._texture is None: self._texture = self._createTexture() glBindTexture(GL_TEXTURE_2D, self._texture) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) for surface in self._vbos: vbo = surface.update length = surface.important vbo.bind() glVertexPointer(3, GL_FLOAT, 4 * 5, vbo) glTexCoordPointer(2, GL_FLOAT, 4 * 5, vbo + (4 * 3)) glDrawArrays(GL_TRIANGLES, 0, length) vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glBindTexture(GL_TEXTURE_2D, 0)
def render(self): vertex = [] for vert, verts in enumerate(self.vertex): vx = numpy.dot(self.vertex[vert], numpy.array([math.cos(math.radians(self.ss.r)), math.sin(math.radians(self.ss.r)), 0, -math.sin(math.radians(self.ss.r)), math.cos(math.radians(self.ss.r)), 0, 0, 0, 1], 'f').reshape(3, 3)) vx = vx + numpy.array([self.ss.x + self.ss.ggci.player.x, self.ss.y + self.ss.ggci.player.y, 0 - self.ss.ggci.player.z], 'f').reshape(1, 3) vertex.append(vx) vertex = numpy.array(vertex, 'f').reshape(len(self.vertex), 3) glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(vertex) glDrawElementsui(GL_POLYGON, self.indices)
def draw_vertices(self): # Draw all the vbo defined in set_atoms if self.transparent: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDepthMask(GL_FALSE) if self.wireframe: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glEnableClientState(GL_VERTEX_ARRAY) self._vbo_v.bind_vertexes(3, GL_FLOAT) glEnableClientState(GL_NORMAL_ARRAY) self._vbo_n.bind_normals(GL_FLOAT) glEnableClientState(GL_COLOR_ARRAY) self._vbo_c.bind_colors(4, GL_UNSIGNED_BYTE) glDrawArrays(GL_TRIANGLES, 0, self._n_triangles) self._vbo_v.unbind() self._vbo_n.unbind() self._vbo_c.unbind() if self.transparent: glDisable(GL_BLEND) #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glDepthMask(GL_TRUE) if self.wireframe: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
def Draw(self, descriptor=[]): """Draws a map with all objects in the world, according to the descriptor.""" GuiObject.Draw(self) # TODO get rid of any frame mechanism parts here frame = self._getFrameData()["frame"] glTranslatef(frame, 2 * frame, 0.0) # moving away from the frame blockSize = (1 - 2 * frame) / self.worldLength scaleFactor = blockSize # data = narray(reduce(lambda a,b: a + b, # map(self.__descToArray, # descriptor)), # "f"); if len(descriptor) > 0: #valuesPerObject = len(self.__descToArray(descriptor[0])) if self._vbo is None: self._BuildData(descriptor) for _id, obj in self._dirty_objects.items(): self._UpdateObject(_id, obj) self._dirty_objects = {} glTranslatef(frame, 2 * frame, 0.0) # moving away from the frame glScale(scaleFactor, scaleFactor, 1.0) self._vbo.bind() self._vbo.copy_data() try: glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_COLOR_ARRAY) # 2 coordinates with 4 color values with 4 bytes each in # between glVertexPointer(2, GL_FLOAT, 24, self._vbo) # 4 color values with 2 coordinates with 4 bytes each in # between glColorPointer(4, GL_FLOAT, 24, self._vbo + 8) glDrawArrays(GL_TRIANGLES, 0, 3 * 2 * (self._max_index + 1)) finally: self._vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY)
def Draw(self, descriptor=[]): """Draws a map with all objects in the world, according to the descriptor.""" GuiObject.Draw(self) # TODO get rid of any frame mechanism parts here frame = self._getFrameData()["frame"] glTranslatef(frame, 2 * frame, 0.0) # moving away from the frame blockSize = (1 - 2 * frame) / self.worldLength scaleFactor = blockSize # data = narray(reduce(lambda a,b: a + b, # map(self.__descToArray, # descriptor)), # "f"); if len(descriptor) > 0: # valuesPerObject = len(self.__descToArray(descriptor[0])) if self._vbo is None: self._BuildData(descriptor) for _id, obj in self._dirty_objects.items(): self._UpdateObject(_id, obj) self._dirty_objects = {} glTranslatef(frame, 2 * frame, 0.0) # moving away from the frame glScale(scaleFactor, scaleFactor, 1.0) self._vbo.bind() self._vbo.copy_data() try: glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_COLOR_ARRAY) # 2 coordinates with 4 color values with 4 bytes each in # between glVertexPointer(2, GL_FLOAT, 24, self._vbo) # 4 color values with 2 coordinates with 4 bytes each in # between glColorPointer(4, GL_FLOAT, 24, self._vbo + 8) glDrawArrays(GL_TRIANGLES, 0, 3 * 2 * (self._max_index + 1)) finally: self._vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY)
def draw(self): ''' Draw the point cloud. ''' glMatrixMode(GL_MODELVIEW) glPushMatrix() glMultMatrixf(self._pose.T) glDisable(GL_LIGHTING) glPointSize(2) if self._xyz_vbo: # ref: http://stackoverflow.com/questions/16558819/vertex-buffer-objects-in-pyopengl-vertex-index-and-colour with self._xyz_vbo: glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(self._xyz_vbo) if self._rgb_vbo: # check for dimension match to avoid segmentation faults if len(self._rgb_vbo) != len(self._xyz_vbo): raise RuntimeError( 'point cloud XYZ and RGB length mismatch: {} vs {}' .format(len(self._xyz_vbo), len(self._rgb_vbo))) with self._rgb_vbo: # add color glEnableClientState(GL_COLOR_ARRAY) glColorPointerf(self._rgb_vbo) glDrawArrays(GL_POINTS, 0, len(self._xyz_vbo)) else: # draw without color glDrawArrays(GL_POINTS, 0, len(self._xyz_vbo)) glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_VERTEX_ARRAY) glEnable(GL_LIGHTING) glPopMatrix()
def drawLineCube(color, pos, radius): vtIndices = [0, 1, 2, 3, 0, 4, 5, 1, 5, 4, 7, 6, 6, 7, 3, 2] glEnableClientState(GL_VERTEX_ARRAY) #bruce 051117 revised this glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices) #grantham 20051213 observations, reported/paraphrased by bruce 051215: # - should verify PyOpenGL turns Python float (i.e. C double) into C # float for OpenGL's GL_FLOAT array element type. # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT # and GL_UNSIGNED_SHORT. glDisable(GL_LIGHTING) glColor3fv(color) glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius, radius, radius) glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4]) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8]) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12]) glPopMatrix() glEnable(GL_LIGHTING) glDisableClientState(GL_VERTEX_ARRAY) return
def drawLineCube(color, pos, radius): vtIndices = [0,1,2,3, 0,4,5,1, 5,4,7,6, 6,7,3,2] glEnableClientState(GL_VERTEX_ARRAY) #bruce 051117 revised this glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices) #grantham 20051213 observations, reported/paraphrased by bruce 051215: # - should verify PyOpenGL turns Python float (i.e. C double) into C # float for OpenGL's GL_FLOAT array element type. # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT # and GL_UNSIGNED_SHORT. glDisable(GL_LIGHTING) glColor3fv(color) glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4]) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8]) #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12]) glPopMatrix() glEnable(GL_LIGHTING) glDisableClientState(GL_VERTEX_ARRAY) return
def draw_vertices(self): # Draw all the vbo defined in set_atoms glEnableClientState(GL_VERTEX_ARRAY) self._vbo_v.bind_vertexes(3, GL_FLOAT) glEnableClientState(GL_NORMAL_ARRAY) self._vbo_n.bind_normals(GL_FLOAT) glEnableClientState(GL_COLOR_ARRAY) self._vbo_c.bind_colors(4, GL_UNSIGNED_BYTE) glDrawArrays(GL_TRIANGLES, 0, self._n_triangles) self._vbo_v.unbind() self._vbo_n.unbind() self._vbo_c.unbind()
def paint(self): self._applyGLOptions() if self.__antialiasing: glEnable(GL_LINE_SMOOTH) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glHint(GL_LINE_SMOOTH_HINT, GL_NICEST) glLineWidth(1.5) if self.draw_faces: # need face with self.shader_program: glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(self.mesh.face_vertices) glColor4f(*self.face_color) glEnableClientState(GL_NORMAL_ARRAY) glNormalPointerf(self.mesh.face_normal_vectors) glDrawArrays(GL_TRIANGLES, 0, np.product(self.mesh.face_vertices.shape[:-1])) glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY) if self.debug_face_normals: # Visualize the face normal vectors glEnableClientState(GL_VERTEX_ARRAY) N = self.mesh.face_vertices.shape[0] * 3 v = np.concatenate([ self.mesh.face_vertices, self.mesh.face_vertices + self.mesh.face_normal_vectors, ]) e = np.array([np.arange(N), np.arange(N) + N]).T.flatten() glColor4f(1.0, 1.0, 0.0, 1.0) glVertexPointerf(v) glDrawElements(GL_LINES, e.shape[0], GL_UNSIGNED_INT, e) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY) if self.debug_face_edges: # visualize all face edges glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(self.mesh.wireframe_vertices) glColor4f(1.0, 1.0, 0.0, 1.0) edges = self.mesh.face_edges.flatten() glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY) if self.draw_wireframe and self.mesh.has_wireframe: # draw a mesh wireframe which may or may not be identical to the face edges, depending on the mesh glEnableClientState(GL_VERTEX_ARRAY) glVertexPointerf(self.mesh.wireframe_vertices) glColor4f(0, 1, 0, 1) edges = self.mesh.wireframe_edges.flatten() glDrawElements(GL_LINES, edges.shape[0], GL_UNSIGNED_INT, edges) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_COLOR_ARRAY)
def draw(self, drawIndex=None, highlighted=False, selected=False, patterning=True, highlight_color=None, opacity=1.0): """ Draw the buffered geometry, binding vertex attribute values for the shaders. If no drawIndex is given, the whole array is drawn. """ self.shader.setActive(True) # Turn on the chosen shader. glEnableClientState(GL_VERTEX_ARRAY) self.shader.setupDraw(highlighted, selected, patterning, highlight_color, opacity) # XXX No transform data until that is more implemented. ###self.shader.setupTransforms(self.transforms) # (note: the reason TransformControls work in their test case # is due to a manual call of shader.setupTransforms. [bruce 090306 guess]) if self.shader.get_TEXTURE_XFORMS(): # Activate a texture unit for transforms. ## XXX Not necessary for custom shader programs. ##glEnable(GL_TEXTURE_2D) glBindTexture(GL_TEXTURE_2D, self.transform_memory) ### BUG: pylint warning: # Instance of 'GLPrimitiveBuffer' has no 'transform_memory' member #### REVIEW: should this be the attr of that name in GLShaderObject, # i.e. self.shader? I didn't fix it myself as a guess, in case other # uses of self also need fixing in the same way. [bruce 090304 comment] # Set the sampler to the handle for the active texture image (0). ## XXX Not needed if only one texture is being used? ##glActiveTexture(GL_TEXTURE0) ##glUniform1iARB(self.shader._uniform("transforms"), 0) pass glDisable(GL_CULL_FACE) # Draw the hunks. for hunkNumber in range(self.nHunks): # Bind the per-vertex generic attribute arrays for one hunk. for buffer in self.hunkBuffers: buffer.flush() # Sync graphics card copies of the VBO data. buffer.bindHunk(hunkNumber) continue # Shared vertex coordinate data VBO: GL_ARRAY_BUFFER_ARB. self.hunkVertVBO.bind() glVertexPointer(3, GL_FLOAT, 0, None) # Shared vertex index data IBO: GL_ELEMENT_ARRAY_BUFFER_ARB self.hunkIndexIBO.bind() if drawIndex is not None: # Draw the selected primitives for this Hunk. index = drawIndex[hunkNumber] primcount = len(index) glMultiDrawElementsVBO(self.drawingMode, self.C_indexBlockLengths, GL_UNSIGNED_INT, index, primcount) else: # For initial testing, draw all primitives in the Hunk. if hunkNumber < self.nHunks - 1: nToDraw = HUNK_SIZE # Hunks before the last. else: nToDraw = self.nPrims - (self.nHunks - 1) * HUNK_SIZE pass glDrawElements(self.drawingMode, self.nIndices * nToDraw, GL_UNSIGNED_INT, None) pass continue self.shader.setActive(False) # Turn off the chosen shader. glEnable(GL_CULL_FACE) self.hunkIndexIBO.unbind() # Deactivate the ibo. self.hunkVertVBO.unbind() # Deactivate all vbo's. glDisableClientState(GL_VERTEX_ARRAY) for buffer in self.hunkBuffers: buffer.unbindHunk() # glDisableVertexAttribArrayARB. continue return
def OnPaint(self, event): # startTime = time.time() if not self.init: self.context = GLContext(self) self.SetCurrent(self.context) glEnable(GL_DEPTH_TEST); self.init = True if self._refreshAll: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # prepareTime = time.time() - startTime if self.dataNum == 0: self.SwapBuffers() return eyePos = self.eyeDistance ex = 0.0 ey = 0.0 ez = 0.0 dx = 0.0 dy = 0.0 dz = 0.0 ux = 0.0 uy = 0.0 uz = 0.0 xLen = max(abs(self.xMax), abs(self.xMin)) * 2 yLen = max(abs(self.yMax), abs(self.yMin)) * 2 zLen = max(abs(self.zMax), abs(self.zMin)) * 2 # print 'transX, transY:', self.transX, self.transY if self.is3D: r2s = max(xLen, yLen, zLen) / self.size.width tX = self.transX * r2s tY = self.transY * r2s if not zLen == 0: z = zLen / 2 if yLen / zLen > self.size.width / self.size.height: z = yLen * self.size.height / self.size.width / 2 z *= 1.5 usedAngle = pi / 2 - viewPosAngle cfovy1 = (eyePos - z * cos(usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(usedAngle)) cfovy2 = (eyePos - z * cos(pi - usedAngle)) / sqrt(eyePos * eyePos + z * z - 2 * eyePos * z * cos(pi - usedAngle)) fovy1 = degrees(acos(cfovy1)) fovy2 = degrees(acos(cfovy2)) self.fovy = 3 * max(fovy1, fovy2) angleX = viewPosAngle + radians(self.angleHorizontal) angleZ = viewPosAngle + radians(self.angleVertical) ex = eyePos * cos(angleZ) * cos(angleX) ey = eyePos * cos(angleZ) * sin(angleX) ez = eyePos * sin(angleZ) ux = 0.0 uy = cos(pi / 2 - radians(self.angleFlat)) uz = sin(pi / 2 - radians(self.angleFlat)) flatAngle = radians(self.angleFlat) dx = -tX * cos(flatAngle) * sin(angleX) - tX * sin(flatAngle) * sin(angleZ) * sin(angleX) dx += tY * sin(flatAngle) * sin(angleX) - tY * cos(flatAngle) * sin(angleZ) * cos(angleX) dy = tX * cos(flatAngle) * cos(angleX) - tX * sin(flatAngle) * sin(angleZ) * cos(angleX) dy += -tY * sin(flatAngle) * cos(angleX) - tY * cos(flatAngle) * sin(angleZ) * sin(angleX) dz = tX * sin(flatAngle) * cos(angleZ) dz += tY * cos(flatAngle) * cos(angleZ) else: r2s = xLen / self.size.width dx = self.transX * r2s dy = self.transY * r2s dz = 0.0 y = yLen / 2 if xLen / yLen > self.size.width / self.size.height: y = xLen * self.size.height / self.size.width / 2 y += yLen / 10 self.fovy = 2 * degrees(atan(y / eyePos)) ez = eyePos ux = sin(radians(self.angleFlat)) uy = cos(radians(self.angleFlat)) uz = 0.0 scale = 1 if self.size != None: scale = float(self.size.width) / self.size.height # userCalculationTime = time.time() - startTime - prepareTime glMatrixMode(GL_PROJECTION) glLoadIdentity() if self.is3D: gluPerspective(self.fovy * self.scaleFactor, scale, 0.1, self.eyeDistance * 2) else: gluPerspective(self.fovy * self.scaleFactor, scale, self.eyeDistance - self.zMax - 10, self.eyeDistance - self.zMin + 10) glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluLookAt(ex, ey, ez, -dx, -dy, -dz, ux, uy, uz) self._startPointIdx = 0 if self.isDragging: # draw the frame instead of all data glLineWidth(1.0) glColor3f(0.0, 0.5, 0.0) glBegin(GL_LINES) glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMin) # 1 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glVertex3f(self.xMin, self.yMin, self.zMax) # 5 glVertex3f(self.xMax, self.yMin, self.zMin) # 2 glVertex3f(self.xMax, self.yMin, self.zMax) # 6 glVertex3f(self.xMax, self.yMax, self.zMin) # 3 glVertex3f(self.xMax, self.yMax, self.zMax) # 7 glVertex3f(self.xMin, self.yMax, self.zMin) # 4 glVertex3f(self.xMin, self.yMax, self.zMax) # 8 glEnd() glFlush() self.SwapBuffers() return glEnableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glEnableClientState(GL_COLOR_ARRAY) glDrawBuffer(GL_FRONT_AND_BACK) if self._startPointIdx + self._drawnPointsNum >= self.dataNum: glDrawArrays(GL_POINTS, self._startPointIdx, self.dataNum - self._startPointIdx) if self.displaySelected: selNum = len(self.displayedSelPoints) if selNum >= 2: glLineWidth(2.0) glColor3f(0.0, 1.0, 0.0) glBegin(GL_LINES) for i in xrange(1, selNum): glVertex3f(self.displayedSelPoints[i - 1][0], self.displayedSelPoints[i - 1][1], self.displayedSelPoints[i - 1][2]) glVertex3f(self.displayedSelPoints[i][0], self.displayedSelPoints[i][1], self.displayedSelPoints[i][2]) glVertex3f(self.displayedSelPoints[selNum - 1][0], self.displayedSelPoints[selNum - 1][1], self.displayedSelPoints[selNum - 1][2]) glVertex3f(self.displayedSelPoints[0][0], self.displayedSelPoints[0][1], self.displayedSelPoints[0][2]) glEnd() self._refreshAll = True else: glDrawArrays(GL_POINTS, self._startPointIdx, self._drawnPointsNum) self._refreshAll = False self._isFront = not self._isFront self._startPointIdx += self._drawnPointsNum if self._isFront else 0 glDisableClientState(GL_VERTEX_ARRAY) if self.colorsNum >= self.dataNum: glDisableClientState(GL_COLOR_ARRAY) glFlush() self.SwapBuffers() # drawingTime = time.time() - startTime - prepareTime - userCalculationTime # print "preparation time:", str(prepareTime), "user calculation time:",\ # str(userCalculationTime), "drawing time:", str(drawingTime) if not self._refreshAll: PostEvent(self, PaintEvent()) event.Skip()
def paint_yuv420(self, img_data, x, y, width, height, rowstrides): #import time #before=time.time() # OpenGL begin if not self.gldrawable.gl_begin(self.glcontext): log.error("OUCH") return False # Upload texture if self.textures[0] == 0: self.textures = glGenTextures(3) glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv420_shader: self.yuv420_shader = [1] glGenProgramsARB(1, self.yuv420_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) # The following fragprog is: # * MIT X11 license, Copyright (c) 2007 by: # * Michael Dominic K. <*****@*****.**> #http://www.mdk.org.pl/2007/11/17/gl-colorspace-conversions prog = """!!ARBfp1.0 # cgc version 3.1.0010, build date Feb 10 2012 # command line args: -profile arbfp1 # source file: yuv.cg #vendor NVIDIA Corporation #version 3.1.0.10 #profile arbfp1 #program main #semantic main.IN #var float2 IN.texcoord1 : $vin.TEXCOORD0 : TEX0 : 0 : 1 #var float2 IN.texcoord2 : $vin.TEXCOORD1 : TEX1 : 0 : 1 #var float2 IN.texcoord3 : $vin.TEXCOORD2 : TEX2 : 0 : 1 #var samplerRECT IN.texture1 : TEXUNIT0 : texunit 0 : 0 : 1 #var samplerRECT IN.texture2 : TEXUNIT1 : texunit 1 : 0 : 1 #var samplerRECT IN.texture3 : TEXUNIT2 : texunit 2 : 0 : 1 #var float4 IN.color : $vin.COLOR0 : COL0 : 0 : 1 #var float4 main.color : $vout.COLOR0 : COL : -1 : 1 #const c[0] = 1.1643835 2.017231 0 0.5 #const c[1] = 0.0625 1.1643835 -0.3917616 -0.81296802 #const c[2] = 1.1643835 0 1.5960271 PARAM c[3] = { { 1.1643835, 2.017231, 0, 0.5 }, { 0.0625, 1.1643835, -0.3917616, -0.81296802 }, { 1.1643835, 0, 1.5960271 } }; TEMP R0; TEMP R1; TEX R0.x, fragment.texcoord[2], texture[2], RECT; ADD R1.z, R0.x, -c[0].w; TEX R1.x, fragment.texcoord[0], texture[0], RECT; TEX R0.x, fragment.texcoord[1], texture[1], RECT; ADD R1.x, R1, -c[1]; ADD R1.y, R0.x, -c[0].w; DP3 result.color.z, R1, c[0]; DP3 result.color.y, R1, c[1].yzww; DP3 result.color.x, R1, c[2]; MOV result.color.w, fragment.color.primary; END # 10 instructions, 2 R-regs """ glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) log.error(glGetString(GL_PROGRAM_ERROR_STRING_ARB)) glEnable(GL_FRAGMENT_PROGRAM_ARB) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[0]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[0]) glActiveTexture(GL_TEXTURE1) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[1]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[1]) glActiveTexture(GL_TEXTURE2) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[2]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[2]) vtxarrays = 0 if vtxarrays == 1: texcoords = [[0, 0], [0, height], [width, height], [width, 0]] vtxcoords = texcoords texcoords_half = [[0, 0], [0, height / 2], [width / 2, height / 2], [width / 2, 0]] glVertexPointeri(vtxcoords) glActiveTexture(GL_TEXTURE0) glClientActiveTexture(GL_TEXTURE0) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glTexCoordPointeri(texcoords) glActiveTexture(GL_TEXTURE1) glClientActiveTexture(GL_TEXTURE1) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glTexCoordPointeri(texcoords_half) glActiveTexture(GL_TEXTURE2) glClientActiveTexture(GL_TEXTURE2) glEnableClientState(GL_TEXTURE_COORD_ARRAY) glTexCoordPointeri(texcoords_half) glDrawArrays(GL_QUADS, 0, 4) else: glBegin(GL_QUADS) glMultiTexCoord2i(GL_TEXTURE0, 0, 0) glMultiTexCoord2i(GL_TEXTURE1, 0, 0) glMultiTexCoord2i(GL_TEXTURE2, 0, 0) glVertex2i(0, 0) glMultiTexCoord2i(GL_TEXTURE0, 0, height) glMultiTexCoord2i(GL_TEXTURE1, 0, height / 2) glMultiTexCoord2i(GL_TEXTURE2, 0, height / 2) glVertex2i(0, height) glMultiTexCoord2i(GL_TEXTURE0, width, height) glMultiTexCoord2i(GL_TEXTURE1, width / 2, height / 2) glMultiTexCoord2i(GL_TEXTURE2, width / 2, height / 2) glVertex2i(width, height) glMultiTexCoord2i(GL_TEXTURE0, width, 0) glMultiTexCoord2i(GL_TEXTURE1, width / 2, 0) glMultiTexCoord2i(GL_TEXTURE2, width / 2, 0) glVertex2i(width, 0) glEnd() # OpenGL end #self.gldrawable.swap_buffers() # self.gldrawable.swap_buffers() glFinish() self.gldrawable.gl_end()
def drawsphere_worker(params): """ Draw a sphere. Receive parameters through a sequence so that this function and its parameters can be passed to another function for deferment. Right now this is only ColorSorter.schedule (see below) """ (pos, radius, detailLevel, n) = params del n # KLUGE: the detailLevel can be a tuple, (vboLevel, detailLevel). # The only for reason for this is that drawsphere_worker is used # in ProteinChunks (I added a comment there saying why that's bad) # and I don't have time to clean that up now. Ideally, vboLevel # would just be another parameter, or we'd combine it with detailLevel # in some other way not constrained by backward compatibility of # this internal worker function's API. [bruce 090304] if type(detailLevel) == type(()): (vboLevel, detailLevel) = detailLevel ## vboLevel = drawing_globals.use_drawing_variant glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) if vboLevel == 0: # OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex. glCallList(drawing_globals.sphereList[detailLevel]) else: # OpenGL 1.1/1.5 - Array/VBO/IBO variants. glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) size = len(drawing_globals.sphereArrays[detailLevel]) GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel] if vboLevel == 1: # DrawArrays from CPU RAM. verts = drawing_globals.sphereCArrays[detailLevel] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) glDrawArrays(GL_TRIANGLE_STRIP, 0, size) elif vboLevel == 2: # DrawElements from CPU RAM. verts = drawing_globals.sphereCElements[detailLevel][1] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) elif vboLevel == 3: # DrawArrays from graphics RAM VBO. vbo = drawing_globals.sphereArrayVBOs[detailLevel] vbo.bind() glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size) vbo.unbind() elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO. vbo = drawing_globals.sphereElementVBOs[detailLevel][1] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) vbo.unbind() elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM. (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) ibo.bind() # Index data comes from the ibo. glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None) vbo.unbind() ibo.unbind() pass glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) pass glPopMatrix() return
def draw_mesh(m, lighting_on): # Supply vertices glEnableClientState(GL_VERTEX_ARRAY) m.vbo['v'].bind() glVertexPointer(3, GL_FLOAT, 0, m.vbo['v']) m.vbo['v'].unbind() # Supply normals if 'vn' in m.vbo.keys(): glEnableClientState(GL_NORMAL_ARRAY) m.vbo['vn'].bind() glNormalPointer(GL_FLOAT, 0, m.vbo['vn']) m.vbo['vn'].unbind() else: glDisableClientState(GL_NORMAL_ARRAY) # Supply colors if 'vc' in m.vbo.keys(): glEnableClientState(GL_COLOR_ARRAY) m.vbo['vc'].bind() glColorPointer(3, GL_FLOAT, 0, m.vbo['vc']) m.vbo['vc'].unbind() else: glDisableClientState(GL_COLOR_ARRAY) if ('vt' in m.vbo.keys()) and hasattr(m, 'textureID'): glEnable(GL_TEXTURE_2D) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glBindTexture(GL_TEXTURE_2D, m.textureID) glEnableClientState(GL_TEXTURE_COORD_ARRAY) m.vbo['vt'].bind() glTexCoordPointer(2, GL_FLOAT, 0, m.vbo['vt']) m.vbo['vt'].unbind() else: glDisable(GL_TEXTURE_2D) glDisableClientState(GL_TEXTURE_COORD_ARRAY) # Draw if len(m.f) > 0: # ie if it is triangulated if lighting_on: glEnable(GL_LIGHTING) else: glDisable(GL_LIGHTING) glDrawElementsui(GL_TRIANGLES, np.arange(m.f.size, dtype=np.uint32)) else: # not triangulated, so disable lighting glDisable(GL_LIGHTING) glPointSize(2) glDrawElementsui(GL_POINTS, np.arange(len(m.v), dtype=np.uint32)) if hasattr(m, 'v_to_text'): glEnable(GL_TEXTURE_2D) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL) # glEnable(GL_TEXTURE_GEN_S) # glEnable(GL_TEXTURE_GEN_T) # glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) # glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR) bgcolor = np.array(glGetDoublev(GL_COLOR_CLEAR_VALUE)) fgcolor = 1. - bgcolor from .lines import Lines sc = float(np.max(np.max(m.v, axis=0) - np.min(m.v, axis=0))) / 10. cur_mtx = np.linalg.pinv(glGetFloatv(GL_MODELVIEW_MATRIX).T) xdir = cur_mtx[:3, 0] ydir = cur_mtx[:3, 1] glEnable(GL_LINE_SMOOTH) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) for vidx, text in m.v_to_text.items(): pos0 = m.v[vidx].copy() pos1 = m.v[vidx].copy() if hasattr(m, 'vn'): pos1 += m.vn[vidx] * sc glLineWidth(5.0) ln = Lines(v=np.vstack((pos0, pos1)), e=np.array([[0, 1]])) glEnable(GL_LIGHTING) glColor3f(1. - 0.8, 1. - 0.8, 1. - 1.00) MeshViewerSingle.draw_lines(ln) glDisable(GL_LIGHTING) texture_id = get_textureid_with_text(text, bgcolor, fgcolor) glBindTexture(GL_TEXTURE_2D, texture_id) glPushMatrix() glTranslatef(pos1[0], pos1[1], pos1[2]) dx = xdir * .10 dy = ydir * .10 if False: glBegin(GL_QUADS) glTexCoord2f(1., 0.) glVertex3f(*(+dx + dy)) glTexCoord2f(1., 1.) glVertex3f(*(+dx - dy)) glTexCoord2f(0., 1.) glVertex3f(*(-dx - dy)) glTexCoord2f(0., 0.) glVertex3f(*(-dx + dy)) # gluSphere(quadratic,0.05,32,32) glEnd() else: glBegin(GL_POLYGON) for r in np.arange(0, np.pi * 2., .01): glTexCoord2f(np.cos(r) / 2. + .5, np.sin(r) / 2. + .5) glVertex3f(*(dx * np.cos(r) + -dy * np.sin(r))) glEnd() glPopMatrix()
def paint_yuv420(self, img_data, x, y, width, height, rowstrides): #import time #before=time.time() # OpenGL begin if not self.gldrawable.gl_begin(self.glcontext): log.error("OUCH") return False # Upload texture if self.textures[0] == 0: self.textures = glGenTextures(3) glEnable(GL_FRAGMENT_PROGRAM_ARB) if not self.yuv420_shader: self.yuv420_shader = [ 1 ] glGenProgramsARB(1, self.yuv420_shader) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) # The following fragprog is: # * MIT X11 license, Copyright (c) 2007 by: # * Michael Dominic K. <*****@*****.**> #http://www.mdk.org.pl/2007/11/17/gl-colorspace-conversions prog = """!!ARBfp1.0 # cgc version 3.1.0010, build date Feb 10 2012 # command line args: -profile arbfp1 # source file: yuv.cg #vendor NVIDIA Corporation #version 3.1.0.10 #profile arbfp1 #program main #semantic main.IN #var float2 IN.texcoord1 : $vin.TEXCOORD0 : TEX0 : 0 : 1 #var float2 IN.texcoord2 : $vin.TEXCOORD1 : TEX1 : 0 : 1 #var float2 IN.texcoord3 : $vin.TEXCOORD2 : TEX2 : 0 : 1 #var samplerRECT IN.texture1 : TEXUNIT0 : texunit 0 : 0 : 1 #var samplerRECT IN.texture2 : TEXUNIT1 : texunit 1 : 0 : 1 #var samplerRECT IN.texture3 : TEXUNIT2 : texunit 2 : 0 : 1 #var float4 IN.color : $vin.COLOR0 : COL0 : 0 : 1 #var float4 main.color : $vout.COLOR0 : COL : -1 : 1 #const c[0] = 1.1643835 2.017231 0 0.5 #const c[1] = 0.0625 1.1643835 -0.3917616 -0.81296802 #const c[2] = 1.1643835 0 1.5960271 PARAM c[3] = { { 1.1643835, 2.017231, 0, 0.5 }, { 0.0625, 1.1643835, -0.3917616, -0.81296802 }, { 1.1643835, 0, 1.5960271 } }; TEMP R0; TEMP R1; TEX R0.x, fragment.texcoord[2], texture[2], RECT; ADD R1.z, R0.x, -c[0].w; TEX R1.x, fragment.texcoord[0], texture[0], RECT; TEX R0.x, fragment.texcoord[1], texture[1], RECT; ADD R1.x, R1, -c[1]; ADD R1.y, R0.x, -c[0].w; DP3 result.color.z, R1, c[0]; DP3 result.color.y, R1, c[1].yzww; DP3 result.color.x, R1, c[2]; MOV result.color.w, fragment.color.primary; END # 10 instructions, 2 R-regs """ glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, len(prog), prog) log.error(glGetString(GL_PROGRAM_ERROR_STRING_ARB)) glEnable(GL_FRAGMENT_PROGRAM_ARB) glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.yuv420_shader[0]) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[0]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[0]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[1]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[1]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[1]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[2]) glEnable(GL_TEXTURE_RECTANGLE_ARB) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[2]) glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[2]); vtxarrays=0 if vtxarrays == 1: texcoords = [ [ 0, 0 ], [ 0, height], [ width, height], [ width, 0] ] vtxcoords = texcoords texcoords_half = [ [ 0, 0 ], [ 0, height/2], [ width/2, height/2], [ width/2, 0] ] glVertexPointeri(vtxcoords) glActiveTexture(GL_TEXTURE0); glClientActiveTexture(GL_TEXTURE0) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointeri(texcoords) glActiveTexture(GL_TEXTURE1); glClientActiveTexture(GL_TEXTURE1) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointeri(texcoords_half) glActiveTexture(GL_TEXTURE2); glClientActiveTexture(GL_TEXTURE2) glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointeri(texcoords_half) glDrawArrays(GL_QUADS, 0, 4); else: glBegin(GL_QUADS); glMultiTexCoord2i(GL_TEXTURE0, 0, 0); glMultiTexCoord2i(GL_TEXTURE1, 0, 0); glMultiTexCoord2i(GL_TEXTURE2, 0, 0); glVertex2i(0, 0); glMultiTexCoord2i(GL_TEXTURE0, 0, height); glMultiTexCoord2i(GL_TEXTURE1, 0, height/2); glMultiTexCoord2i(GL_TEXTURE2, 0, height/2); glVertex2i(0, height); glMultiTexCoord2i(GL_TEXTURE0, width, height); glMultiTexCoord2i(GL_TEXTURE1, width/2, height/2); glMultiTexCoord2i(GL_TEXTURE2, width/2, height/2); glVertex2i(width, height); glMultiTexCoord2i(GL_TEXTURE0, width, 0); glMultiTexCoord2i(GL_TEXTURE1, width/2, 0); glMultiTexCoord2i(GL_TEXTURE2, width/2, 0); glVertex2i(width, 0); glEnd() # OpenGL end #self.gldrawable.swap_buffers() # self.gldrawable.swap_buffers() glFinish() self.gldrawable.gl_end()
def drawHeightfield(color, w, h, textureReady, opacity, SOLID=False, pickCheckOnly=False, hf=None): """ Draw a heighfield using vertex and normal arrays. Optionally, it could be texuture mapped. @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick selection purpose. """ from OpenGL.GL import glTexEnvf from OpenGL.GL import GL_TEXTURE_ENV from OpenGL.GL import GL_TEXTURE_ENV_MODE from OpenGL.GL import GL_MODULATE from OpenGL.GL import glVertexPointer from OpenGL.GL import glNormalPointer from OpenGL.GL import glTexCoordPointer from OpenGL.GL import glDrawArrays from OpenGL.GL import glEnableClientState from OpenGL.GL import GL_VERTEX_ARRAY from OpenGL.GL import GL_NORMAL_ARRAY from OpenGL.GL import GL_TEXTURE_COORD_ARRAY glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) ### glColor4fv(list(color) + [opacity]) ### glColor3fv(list(color)) glColor3f(1.0, 1.0, 1.0) glPushMatrix() glScalef(w, h, 1.0) if SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) else: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glDisable(GL_CULL_FACE) if not pickCheckOnly: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) if textureReady: glEnable(GL_TEXTURE_2D) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) for tstrip_vert, tstrip_norm, tstrip_tex in hf: glVertexPointer(3, GL_FLOAT, 0, tstrip_vert) glNormalPointer(GL_FLOAT, 0, tstrip_norm) glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex) glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert)) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_COLOR_MATERIAL) if not pickCheckOnly: if textureReady: glDisable(GL_TEXTURE_2D) glDepthMask(GL_TRUE) glEnable(GL_CULL_FACE) if not SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glPopMatrix() glEnable(GL_LIGHTING) return
def drawsphere_worker(params): """ Draw a sphere. Receive parameters through a sequence so that this function and its parameters can be passed to another function for deferment. Right now this is only ColorSorter.schedule (see below) """ (pos, radius, detailLevel) = params vboLevel = drawing_globals.use_drawing_variant glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) if vboLevel == 0: glCallList(drawing_globals.sphereList[detailLevel]) else: # Array variants. glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) size = len(drawing_globals.sphereArrays[detailLevel]) GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel] if vboLevel == 1: # DrawArrays from CPU RAM. verts = drawing_globals.sphereCArrays[detailLevel] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) glDrawArrays(GL_TRIANGLE_STRIP, 0, size) elif vboLevel == 2: # DrawElements from CPU RAM. verts = drawing_globals.sphereCElements[detailLevel][1] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) elif vboLevel == 3: # DrawArrays from graphics RAM VBO. vbo = drawing_globals.sphereArrayVBOs[detailLevel] vbo.bind() glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size) vbo.unbind() elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO. vbo = drawing_globals.sphereElementVBOs[detailLevel][1] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) vbo.unbind() elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM. (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) ibo.bind() # Index data comes from the ibo. glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None) vbo.unbind() ibo.unbind() pass glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) pass glPopMatrix() return
def drawHeightfield(color, w, h, textureReady, opacity, SOLID=False, pickCheckOnly=False, hf=None): """ Draw a heighfield using vertex and normal arrays. Optionally, it could be texture mapped. @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick selection purpose. """ if not hf: # Return if heightfield is not provided return glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) # Don't use opacity, otherwise the heighfield polygons should be sorted # - something to implement later... ## glColor3v(list(color)) if textureReady: # For texturing, use white color (to be modulated by the texture) glColor3f(1, 1, 1) else: glColor3fv(list(color)) glPushMatrix() glScalef(w, h, 1.0) if SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) else: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glDisable(GL_CULL_FACE) if not pickCheckOnly: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) if textureReady: glEnable(GL_TEXTURE_2D) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) for tstrip_vert, tstrip_norm, tstrip_tex in hf: glVertexPointer(3, GL_FLOAT, 0, tstrip_vert) glNormalPointer(GL_FLOAT, 0, tstrip_norm) glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex) glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert)) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_COLOR_MATERIAL) if not pickCheckOnly: if textureReady: glDisable(GL_TEXTURE_2D) glDepthMask(GL_TRUE) glEnable(GL_CULL_FACE) if not SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glPopMatrix() glEnable(GL_LIGHTING) return
def test_drawing(glpane, initOnly=False): """ When TEST_DRAWING is enabled at the start of graphics/widgets/GLPane_rendering_methods.py, and when TestGraphics_Command is run (see its documentation for various ways to do that), this file is loaded and GLPane.paintGL() calls the test_drawing() function instead of the usual body of paintGL(). """ # WARNING: this duplicates some code with test_Draw_model(). # Load the sphere shaders if needed. global _USE_SHADERS if _USE_SHADERS: if not drawing_globals.test_sphereShader: print "test_drawing: Loading sphere shaders." try: from graphics.drawing.gl_shaders import GLSphereShaderObject drawing_globals.test_sphereShader = GLSphereShaderObject() ##### REVIEW: is this compatible with my refactoring in drawing_globals? # If not, use of Test Graphics Performance command might cause subsequent # bugs in other code. Ideally we'd call the new methods that encapsulate # this, to setup shaders. [bruce 090304 comment] print "test_drawing: Sphere-shader initialization is complete.\n" except: _USE_SHADERS = False print "test_drawing: Exception while loading sphere shaders, will reraise and not try again" raise pass global start_pos, first_time if first_time: # Set up the viewing scale, but then let interactive zooming work. glpane.scale = nSpheres * .6 pass # This same function gets called to set up for drawing, and to draw. if not initOnly: glpane._setup_modelview() glpane._setup_projection() ##glpane._compute_frustum_planes() glClearColor(64.0, 64.0, 64.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) ##glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glMatrixMode(GL_MODELVIEW) pass global test_csdl, test_dl, test_dls, test_ibo, test_vbo, test_spheres global test_DrawingSet, test_endpoints, test_Object # See below for test case descriptions and timings on a MacBook Pro. # The Qt event toploop in NE1 tops out at about 60 frames-per-second. # NE1 with test toploop, single CSDL per draw (test case 1) # . 17,424 spheres (132x132, through the color sorter) 4.8 FPS # Russ 080919: More recently, 12.2 FPS. # . Level 2 spheres have 9 triangles x 20 faces, 162 distinct vertices, # visited on the average 2.3 times, giving 384 tri-strip vertices. # . 17,424 spheres is 6.7 million tri-strip vertices. (6,690,816) if testCase == 1: if test_csdl is None: print("Test case 1, %d^2 spheres\n %s." % (nSpheres, "ColorSorter")) test_csdl = ColorSortedDisplayList() ColorSorter.start(None, test_csdl) drawsphere( [0.5, 0.5, 0.5], # color [0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, testloop=nSpheres) ColorSorter.finish(draw_now=True) pass else: test_csdl.draw() pass # NE1 with test toploop, single display list per draw (test case 2) # . 10,000 spheres (all drawing modes) 17.5 FPS # . 17,424 spheres (132x132, manual display list) 11.1 FPS # . 40,000 spheres (mode 5 - VBO/IBO spheres from DL's) 2.2 FPS # . 40,000 spheres (mode 6 - Sphere shaders from DL's) 2.5 FPS # . 90,000 spheres (all drawing modes) 1.1 FPS elif testCase == 2: if test_dl is None: print("Test case 2, %d^2 spheres\n %s." % (nSpheres, "One display list calling primitive dl's")) test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) drawsphere_worker_loop(( [0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, nSpheres)) glEndList() pass else: glColor3i(127, 127, 127) glCallList(test_dl) pass # NE1 with test toploop, one big chunk VBO/IBO of box quads (test case 3) # . 17,424 spheres (1 box/shader draw call) 43.7 FPS # . 17,424 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 57.7 FPS # . 40,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 56.7 FPS # . 90,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 52.7 FPS # . 160,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 41.4 FPS # . 250,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 27.0 FPS elif int(testCase) == 3: doTransforms = False if test_spheres is None: print("Test case 3, %d^2 spheres\n %s." % (nSpheres, "One big VBO/IBO chunk buffer")) if testCase == 3.1: print("Sub-test 3.1, animate partial updates.") elif testCase == 3.2: print("Sub-test 3.2, animate partial updates" + " w/ C per-chunk array buffering.") elif testCase == 3.3: print("Sub-test 3.3, animate partial updates" + " w/ Python array buffering.") # . 3.4 - Big batch draw, with transforms indexed by IDs added. # (Second FPS number with debug colors in the vertex shader off.) # - 90,000 (300x300) spheres, TEXTURE_XFORMS = True, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 250, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 275, 0.3(0.6) FPS # (What happens after 250? CPU usage goes from 40% to 94%.) # -160,000 (400x400) spheres, TEXTURE_XFORMS = True, 26 FPS # -250,000 (500x500) spheres, TEXTURE_XFORMS = True, 26 FPS elif testCase == 3.4: print("Sub-test 3.4, add transforms indexed by IDs.") from graphics.drawing.gl_shaders import TEXTURE_XFORMS from graphics.drawing.gl_shaders import N_CONST_XFORMS from graphics.drawing.gl_shaders import UNIFORM_XFORMS if TEXTURE_XFORMS: print "Transforms in texture memory." elif UNIFORM_XFORMS: print "%d transforms in uniform memory." % N_CONST_XFORMS pass else: print "transforms not supported, error is likely" doTransforms = True pass centers = [] radius = .5 radii = [] colors = [] if not doTransforms: transformIDs = None else: transformIDs = [] transformChunkID = -1 # Allocate IDs sequentially from 0. # For this test, allow arbitrarily chunking the primitives. primCounter = transformChunkLength transforms = [] # Accumulate transforms as a list of lists. # Initialize transforms with an identity matrix. # Transforms here are lists (or Numpy arrays) of 16 numbers. identity = ([1.0] + 4 * [0.0]) * 3 + [1.0] pass for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. thisRad = radius * (.75 + t * .25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Transforms go into a texture memory image if needed. # Per-primitive Transform IDs go into an attribute VBO. if doTransforms: primCounter = primCounter + 1 if primCounter >= transformChunkLength: # Start a new chunk, allocating a transform matrix. primCounter = 0 transformChunkID += 1 if 0: # 1 # Debug hack: Label mat[0,0] with the chunk ID. # Vertex shader debug code shows these in blue. # If viewed as geometry, it will be a slight # stretch of the array in the X direction. transforms += [ [1.0 + transformChunkID / 100.0] + identity[1:] ] elif 0: # 1 # Debug hack: Fill mat with mat.element pattern. transforms += [[ transformChunkID + i / 100.0 for i in range(16) ]] else: transforms += [identity] pass pass # All of the primitives in a chunk have the same ID. transformIDs += [transformChunkID] pass continue continue test_spheres = GLSphereBuffer() test_spheres.addSpheres(centers, radii, colors, transformIDs, None) if doTransforms: print("%d primitives in %d transform chunks of size <= %d" % (nSpheres * nSpheres, len(transforms), transformChunkLength)) shader = drawing_globals.test_sphereShader shader.setupTransforms(transforms) pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Update portions for animation. pulse = time.time() pulse -= floor(pulse) # 0 to 1 in each second # Test animating updates on 80% of the radii in 45% of the columns. # . 3.1 - Update radii Python array per-column, send to graphics RAM. # - 2,500 (50x50) spheres 55 FPS # - 10,000 (100x100) spheres 35 FPS # - 17,424 (132x132) spheres 22.2 FPS # - 40,000 (200x200) spheres 12.4 FPS # - 90,000 (300x300) spheres 6.0 FPS if testCase == 3.1: # Not buffered, send each column change. radius = .5 margin = nSpheres / 10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres - margin): t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t * .25) phase = pulse + float(x + y) / nSpheres radii += 8 * [thisRad - .1 + .1 * sin(phase * 2 * pi)] continue C_radii = numpy.array(radii, dtype=numpy.float32) offset = x * nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_radii) continue pass # . 3.2 - Numpy buffered in C array, subscript assignments to C. # - 2,500 (50x50) spheres 48 FPS # - 10,000 (100x100) spheres 17.4 FPS # - 17,424 (132x132) spheres 11.2 FPS # - 40,000 (200x200) spheres 5.5 FPS # - 90,000 (300x300) spheres 2.5 FPS elif testCase == 3.2: # Buffered per-chunk at the C array level. radius = .5 margin = nSpheres / 10 global C_array if C_array is None: # Replicate. C_array = numpy.zeros((8 * (nSpheres - (2 * margin)), ), dtype=numpy.float32) pass for x in range(margin, nSpheres, 2): count = 0 for y in range(margin, nSpheres - margin): t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t * .25) phase = pulse + float(x + y) / nSpheres C_array[count*8:(count+1)*8] = \ thisRad-.1 + .1*sin(phase * 2*pi) count += 1 continue offset = x * nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_array) continue pass # . 3.3 - updateRadii in Python array, copy via C to graphics RAM. # - 2,500 (50x50) spheres 57 FPS # - 10,000 (100x100) spheres 32 FPS # - 17,424 (132x132) spheres 20 FPS # - 40,000 (200x200) spheres 10.6 FPS # - 90,000 (300x300) spheres 4.9 FPS elif testCase == 3.3: # Buffered at the Python level, batch the whole-array update. radius = .5 margin = nSpheres / 10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres - margin): t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t * .25) phase = pulse + float(x + y) / nSpheres radii += [thisRad - .1 + .1 * sin(phase * 2 * pi)] continue test_spheres.updateRadii( # Update, but don't send yet. x * nSpheres + margin, radii, send=False) continue test_spheres.sendRadii() pass # Options: color = [0.0, 1.0, 0.0], transform_id = 1, radius = 1.0 test_spheres.draw() pass # NE1 with test toploop, separate sphere VBO/IBO box/shader draws (test case 4) # . 17,424 spheres (132x132 box/shader draw quads calls) 0.7 FPS elif testCase == 4: if test_ibo is None: print("Test case 4, %d^2 spheres\n %s." % (nSpheres, "Separate VBO/IBO shader/box buffer sphere calls, no DL")) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() pass else: drawing_globals.test_sphereShader.configShader(glpane) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius, radius, radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) pass # NE1 with test toploop, # One DL around separate VBO/IBO shader/box buffer sphere calls (test case 5) # . 17,424 spheres (1 box/shader DL draw call) 9.2 FPS elif testCase == 5: if test_dl is None: print("Test case 5, %d^2 spheres\n %s." % ( nSpheres, "One DL around separate VBO/IBO shader/box buffer sphere calls" )) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() # Wrap a display list around the draws. test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius, radius, radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glEndList() else: glColor3i(127, 127, 127) glCallList(test_dl) pass pass # NE1 with test toploop, # N column DL's around VBO/IBO shader/box buffer sphere calls (test case 6) # . 2,500 (50x50) spheres 58 FPS # . 10,000 (100x100) spheres 57 FPS # . 17,424 (132x132) spheres 56 FPS # . 40,000 (200x200) spheres 50 FPS # . 90,000 (300x300) spheres 28 FPS # . 160,000 (400x400) spheres 16.5 FPS # . 250,000 (500x500) spheres 3.2 FPS elif testCase == 6: if test_dls is None: print("Test case 6, %d^2 spheres\n %s." % (nSpheres, "N col DL's around VBO/IBO shader/box buffer sphere calls")) # Wrap n display lists around the draws (one per column.) test_dls = glGenLists( nSpheres) # Returns ID of first DL in the set. test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] # Each column is relative to its bottom sphere location. Start # at the lower-left corner, offset so the whole pattern comes up # centered on the origin. start_pos = V(0, 0, 0) # So it doesn't get subtracted twice. pos = sphereLoc(x, 0) - V(nSpheres / 2.0, nSpheres / 2.0, 0) for y in range(nSpheres): centers += [sphereLoc(0, y)] # Sphere radii progress from 3/4 to full size. t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. thisRad = radius * (.75 + t * .25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue test_sphere = GLSphereBuffer() test_sphere.addSpheres(centers, radii, colors, None, None) test_spheres += [test_sphere] glNewList(test_dls + x, GL_COMPILE_AND_EXECUTE) glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) test_sphere.draw() glPopMatrix() glEndList() continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Turn the lights on. for x in range(nSpheres): glCallList(test_dls + x) continue pass pass # NE1 with test toploop, # N column VBO sets of shader/box buffer sphere calls (test case 7) # . 2,500 (50x50) spheres 50 FPS # . 10,000 (100x100) spheres 30.5 FPS # . 17,424 (132x132) spheres 23.5 FPS # . 40,000 (200x200) spheres 16.8 FPS # . 90,000 (300x300) spheres 10.8 FPS # . 160,000 (400x400) spheres 9.1 FPS # . 250,000 (500x500) spheres 7.3 FPS elif testCase == 7: if test_spheres is None: print("Test case 7, %d^2 spheres\n %s." % (nSpheres, "Per-column VBO/IBO chunk buffers")) test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. thisRad = radius * (.75 + t * .25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue _spheres1 = GLSphereBuffer() _spheres1.addSpheres(centers, radii, colors, None, None) test_spheres += [_spheres1] continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) for chunk in test_spheres: chunk.draw() pass # NE1 with test toploop, # Short chunk VBO sets of shader/box buffer sphere calls (test case 8) # . 625 (25x25) spheres 30 FPS, 79 chunk buffers of length 8. # . 2,500 (50x50) spheres 13.6 FPS, 313 chunk buffers of length 8. # . 10,000 (100x100) spheres 6.4 FPS, 704 chunk buffers of length 8. # . 10,000 (100x100) spheres 3.3 FPS, 1250 chunk buffers of length 8. # . 17,424 (132x132) spheres 2.1 FPS, 2178 chunk buffers of length 8. # . 2,500 (50x50) spheres 33.5 FPS, 105 chunk buffers of length 24. # . 17,424 (132x132) spheres 5.5 FPS, 726 chunk buffers of length 24. # # Subcase 8.1: CSDLs in a DrawingSet. (Initial pass-through version.) # . 2,500 (50x50) spheres 36.5 FPS, 105 chunk buffers of length 24. # . 5,625 (75x75) spheres 16.1 FPS, 235 chunk buffers of length 24. # . 10,000 (100x100) spheres 0.5 FPS?!, 414 chunk buffers of length 24. # Has to be <= 250 chunks for constant memory transforms? # . 10,000 (100x100) spheres 11.8 FPS, 50 chunk buffers of length 200. # After a minute of startup. # . 10,000 (100x100) spheres 9.3 FPS, 200 chunk buffers of length 50. # After a few minutes of startup. # Subcase 8.2: CSDLs in a DrawingSet with transforms. (Pass-through.) # . 10,000 (100x100) spheres 11.5 FPS, 50 chunk buffers of length 200. # # Subcase 8.1: CSDLs in a DrawingSet. (First HunkBuffer version.) # Measured with auto-rotate on, ignoring startup and occasional outliers. # As before, on a 2 core, 2.4 GHz Intel MacBook Pro with GeForce 8600M GT. # HUNK_SIZE = 10000 # . 2,500 (50x50) spheres 140-200 FPS, 105 chunks of length 24. # . 5,625 (75x75) spheres 155-175 FPS, 235 chunks of length 24. # . 10,000 (100x100) spheres 134-145 FPS, 50 chunks of length 200. # . 10,000 (100x100) spheres 130-143 FPS, 200 chunks of length 50. # . 10,000 (100x100) spheres 131-140 FPS, 1,250 chunks of length 8. # Chunks are gathered into hunk buffers, so no chunk size speed diff. # . 17,424 (132x132) spheres 134-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 131-140 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 20000 # . 17,424 (132x132) spheres 131-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 130-141 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 10000 # . 40,000 (200x200) spheres 77.5-82.8 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 34.9-42.6 FPS, 11,2500 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # Rotate the sphere-array off-axis 45 degrees to minimize. # (Try adding multi-sampled anti-aliasing, to the drawing test...) # . 160,000 (400x400) spheres 26.4-27.1 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.8-17.1 FPS, 31,250 chunks of length 8. # The pattern is getting too large, far-clipping is setting in. # . 360,000 (600x600) spheres 11.6-11.8 FPS, 45,000 chunks of length 8. # Extreme far-clipping in the drawing test pattern. # HUNK_SIZE = 20000; no significant speed-up. # . 40,000 (200x200) spheres 75.9-81.5 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 41.2-42.4 FPS, 11,250 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # . 160,000 (400x400) spheres 26.5-26.9 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.5-17.1 FPS, 31,250 chunks of length 8. # . 360,000 (600x600) spheres 11.8-12.1 FPS, 45,000 chunks of length 8. # HUNK_SIZE = 5000; no significant slowdown or CPU load difference. # . 40,000 (200x200) spheres 81.0-83.8 FPS, 5,000 chunks of length 8. # . 160,000 (400x400) spheres 27.3-29.4 FPS, 20,000 chunks of length 8. # . 360,000 (600x600) spheres 11.7-12.1 FPS, 45,000 chunks of length 8. # # Retest after updating MacOS to 10.5.5, with TestGraphics, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 68.7-74.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 39.4-42.0 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 24.4-25.2 FPS, 20,000 chunks of length 8. # Retest with glMultiDrawElements drawing indexes in use, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 52.8-54.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 22.8-23.3 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 13.5-15.2 FPS, 20,000 chunks of length 8. # # Retest with reworked halo/sphere shader, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 52.8-53.7 FPS, 2,178 chunks of length 8. [60] # . 40,000 (200x200) spheres 29.3-30.4 FPS, 5,000 chunks of length 8.[156] # . 90,000 (300x300) spheres 18.2-19.2 FPS, 11,250 chunks of length 8.[381] # . 160,000 (400x400) spheres 10.2-11.6 FPS, 20,000 chunks of length 8.[747] # Billboard drawing patterns instead of cubes, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 49.7-55.7 FPS, 2,178 chunks of length 8. [35] # . 40,000 (200x200) spheres 39.6-40.8 FPS, 5,000 chunks of length 8. [88] # . 90,000 (300x300) spheres 18.9-19.5 FPS, 11,250 chunks of length 8.[225] # . 160,000 (400x400) spheres 11.2-11.7 FPS, 20,000 chunks of length 8.[476] # elif int(testCase) == 8: doTransforms = False doCylinders = False if test_spheres is None: # Setup. print("Test case 8, %d^2 primitives\n %s, length %d." % (nSpheres, "Short VBO/IBO chunk buffers", chunkLength)) if testCase == 8.1: print( "Sub-test 8.1, sphere chunks are in CSDL's in a DrawingSet." ) test_DrawingSet = DrawingSet() elif testCase == 8.2: print("Sub-test 8.2, spheres, rotate with TransformControls.") test_DrawingSet = DrawingSet() doTransforms = True elif testCase == 8.3: print( "Sub-test 8.3, cylinder chunks are in CSDL's in a DrawingSet." ) test_DrawingSet = DrawingSet() doCylinders = True pass if test_DrawingSet: # note: doesn't happen in test 8.0, which causes a bug then. [bruce 090223 comment] print "constructed test_DrawingSet =", test_DrawingSet if USE_GRAPHICSMODE_DRAW: print("Use graphicsMode.Draw_model for DrawingSet in paintGL.") pass t1 = time.time() if doTransforms: # Provide several TransformControls to test separate action. global numTCs, TCs numTCs = 3 TCs = [TransformControl() for i in range(numTCs)] pass def primCSDL(centers, radii, colors): if not doTransforms: csdl = ColorSortedDisplayList() # Transformless. else: # Test pattern for TransformControl usage - vertical columns # of TC domains, separated by X coord of first center point. # Chunking will be visible when transforms are changed. xCoord = centers[0][0] - start_pos[ 0] # Negate centering X. xPercent = ( xCoord / (nSpheres + nSpheres / 10 + nSpheres / 100 - 1 + (nSpheres <= 1))) xTenth = int(xPercent * 10 + .5) csdl = ColorSortedDisplayList(TCs[xTenth % numTCs]) pass # Test selection using the CSDL glname. ColorSorter.pushName(csdl.glname) ColorSorter.start(glpane, csdl) for (color, center, radius) in zip(colors, centers, radii): if not doCylinders: # Through ColorSorter to the sphere primitive buffer... drawsphere(color, center, radius, DRAWSPHERE_DETAIL_LEVEL) else: # Through ColorSorter to cylinder primitive buffer... if not drawing_globals.cylinderShader_available(): print "warning: not cylinderShader_available(), error is likely:" if (True and # Whether to do tapered shader-cylinders. # Display List cylinders don't support taper. glpane.glprefs.cylinderShader_desired()): ###cylRad = (radius/2.0, (.75-radius)/2.0) cylRad = (radius / 1.5 - .167, .3 - radius / 1.5) else: cylRad = radius / 2.0 pass endPt2 = center + V(0.5, 0.0, 0.0) # 0.5, -0.5) drawcylinder(color, center, endPt2, cylRad) global test_endpoints test_endpoints += [(center, endPt2)] pass continue ColorSorter.popName() ColorSorter.finish(draw_now=True) test_DrawingSet.addCSDL(csdl) return csdl if testCase == 8: #bruce 090223 revised to try to avoid traceback def chunkFn(centers, radii, colors): res = GLSphereBuffer() res.addSpheres(centers, radii, colors, None, None) return res pass else: chunkFn = primCSDL pass test_spheres = [] radius = .5 centers = [] radii = [] colors = [] global test_endpoints test_endpoints = [] for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x + y) / (nSpheres + nSpheres ) # 0 to 1 fraction. thisRad = radius * (.5 + t * .5) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Put out short chunk buffers. if len(centers) >= chunkLength: test_spheres += [chunkFn(centers, radii, colors)] centers = [] radii = [] colors = [] continue continue # Remainder fraction buffer. if len(centers): test_spheres += [chunkFn(centers, radii, colors)] pass print "Setup time", time.time() - t1, "seconds." print "%d chunk buffers" % len(test_spheres) pass elif not initOnly: # Run. test_Draw_8x(glpane) pass elif testCase == 100: #bruce 090102 # before making more of these, modularize it somehow from commands.TestGraphics.test_selection_redraw import test_selection_redraw test_class = test_selection_redraw params = (nSpheres, ) # note: test size is not directly comparable to other tests with same value of nSpheres if test_Object is None \ or not isinstance(test_Object, test_class) \ or test_Object.current_params() != params: # review: same_vals? # Setup. if test_Object: test_Object.destroy() test_Object = test_class(*params) test_Object.activate() print test_Object pass # review: safe to change elif to if? not sure, GL state is only initialized below elif not initOnly: # Run. test_Object.draw_complete() pass pass if not initOnly: glMatrixMode(GL_MODELVIEW) glFlush() pass first_time = False return
def drawsphere_worker(params): """ Draw a sphere. Receive parameters through a sequence so that this function and its parameters can be passed to another function for deferment. Right now this is only ColorSorter.schedule (see below) """ (pos, radius, detailLevel, n) = params del n # KLUGE: the detailLevel can be a tuple, (vboLevel, detailLevel). # The only for reason for this is that drawsphere_worker is used # in ProteinChunks (I added a comment there saying why that's bad) # and I don't have time to clean that up now. Ideally, vboLevel # would just be another parameter, or we'd combine it with detailLevel # in some other way not constrained by backward compatibility of # this internal worker function's API. [bruce 090304] if type(detailLevel) == type(()): (vboLevel, detailLevel) = detailLevel ## vboLevel = drawing_globals.use_drawing_variant glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius, radius, radius) if vboLevel == 0: # OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex. glCallList(drawing_globals.sphereList[detailLevel]) else: # OpenGL 1.1/1.5 - Array/VBO/IBO variants. glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) size = len(drawing_globals.sphereArrays[detailLevel]) GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel] if vboLevel == 1: # DrawArrays from CPU RAM. verts = drawing_globals.sphereCArrays[detailLevel] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) glDrawArrays(GL_TRIANGLE_STRIP, 0, size) elif vboLevel == 2: # DrawElements from CPU RAM. verts = drawing_globals.sphereCElements[detailLevel][1] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) elif vboLevel == 3: # DrawArrays from graphics RAM VBO. vbo = drawing_globals.sphereArrayVBOs[detailLevel] vbo.bind() glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size) vbo.unbind() elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO. vbo = drawing_globals.sphereElementVBOs[detailLevel][1] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) vbo.unbind() elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM. (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) ibo.bind() # Index data comes from the ibo. glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None) vbo.unbind() ibo.unbind() pass glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) pass glPopMatrix() return
def draw(self, drawIndex = None, highlighted = False, selected = False, patterning = True, highlight_color = None, opacity = 1.0): """ Draw the buffered geometry, binding vertex attribute values for the shaders. If no drawIndex is given, the whole array is drawn. """ self.shader.setActive(True) # Turn on the chosen shader. glEnableClientState(GL_VERTEX_ARRAY) self.shader.setupDraw(highlighted, selected, patterning, highlight_color, opacity) # XXX No transform data until that is more implemented. ###self.shader.setupTransforms(self.transforms) # (note: the reason TransformControls work in their test case # is due to a manual call of shader.setupTransforms. [bruce 090306 guess]) if self.shader.get_TEXTURE_XFORMS(): # Activate a texture unit for transforms. ## XXX Not necessary for custom shader programs. ##glEnable(GL_TEXTURE_2D) glBindTexture(GL_TEXTURE_2D, self.transform_memory) ### BUG: pylint warning: # Instance of 'GLPrimitiveBuffer' has no 'transform_memory' member #### REVIEW: should this be the attr of that name in GLShaderObject, # i.e. self.shader? I didn't fix it myself as a guess, in case other # uses of self also need fixing in the same way. [bruce 090304 comment] # Set the sampler to the handle for the active texture image (0). ## XXX Not needed if only one texture is being used? ##glActiveTexture(GL_TEXTURE0) ##glUniform1iARB(self.shader._uniform("transforms"), 0) pass glDisable(GL_CULL_FACE) # Draw the hunks. for hunkNumber in range(self.nHunks): # Bind the per-vertex generic attribute arrays for one hunk. for buffer in self.hunkBuffers: buffer.flush() # Sync graphics card copies of the VBO data. buffer.bindHunk(hunkNumber) continue # Shared vertex coordinate data VBO: GL_ARRAY_BUFFER_ARB. self.hunkVertVBO.bind() glVertexPointer(3, GL_FLOAT, 0, None) # Shared vertex index data IBO: GL_ELEMENT_ARRAY_BUFFER_ARB self.hunkIndexIBO.bind() if drawIndex is not None: # Draw the selected primitives for this Hunk. index = drawIndex[hunkNumber] primcount = len(index) glMultiDrawElementsVBO( self.drawingMode, self.C_indexBlockLengths, GL_UNSIGNED_INT, index, primcount) else: # For initial testing, draw all primitives in the Hunk. if hunkNumber < self.nHunks-1: nToDraw = HUNK_SIZE # Hunks before the last. else: nToDraw = self.nPrims - (self.nHunks-1) * HUNK_SIZE pass glDrawElements(self.drawingMode, self.nIndices * nToDraw, GL_UNSIGNED_INT, None) pass continue self.shader.setActive(False) # Turn off the chosen shader. glEnable(GL_CULL_FACE) self.hunkIndexIBO.unbind() # Deactivate the ibo. self.hunkVertVBO.unbind() # Deactivate all vbo's. glDisableClientState(GL_VERTEX_ARRAY) for buffer in self.hunkBuffers: buffer.unbindHunk() # glDisableVertexAttribArrayARB. continue return
def drawsphere_worker(params): """ Draw a sphere. Receive parameters through a sequence so that this function and its parameters can be passed to another function for deferment. Right now this is only ColorSorter.schedule (see below) """ (pos, radius, detailLevel) = params vboLevel = drawing_globals.use_drawing_variant glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius, radius, radius) if vboLevel == 0: glCallList(drawing_globals.sphereList[detailLevel]) else: # Array variants. glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) size = len(drawing_globals.sphereArrays[detailLevel]) GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel] if vboLevel == 1: # DrawArrays from CPU RAM. verts = drawing_globals.sphereCArrays[detailLevel] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) glDrawArrays(GL_TRIANGLE_STRIP, 0, size) elif vboLevel == 2: # DrawElements from CPU RAM. verts = drawing_globals.sphereCElements[detailLevel][1] glVertexPointer(3, GL_FLOAT, 0, verts) glNormalPointer(GL_FLOAT, 0, verts) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) elif vboLevel == 3: # DrawArrays from graphics RAM VBO. vbo = drawing_globals.sphereArrayVBOs[detailLevel] vbo.bind() glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size) vbo.unbind() elif vboLevel == 4: # DrawElements from index in CPU RAM, verts in VBO. vbo = drawing_globals.sphereElementVBOs[detailLevel][1] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug. index = drawing_globals.sphereElements[detailLevel][0] glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index) vbo.unbind() elif vboLevel == 5: # VBO/IBO buffered DrawElements from graphics RAM. (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel] vbo.bind() # Vertex and normal data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) glNormalPointer(GL_FLOAT, 0, None) ibo.bind() # Index data comes from the ibo. glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None) vbo.unbind() ibo.unbind() pass glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) pass glPopMatrix() return
def test_drawing(glpane, initOnly = False): """ When TEST_DRAWING is enabled at the start of graphics/widgets/GLPane_rendering_methods.py, and when TestGraphics_Command is run (see its documentation for various ways to do that), this file is loaded and GLPane.paintGL() calls the test_drawing() function instead of the usual body of paintGL(). """ # WARNING: this duplicates some code with test_Draw_model(). # Load the sphere shaders if needed. global _USE_SHADERS if _USE_SHADERS: if not drawing_globals.test_sphereShader: print "test_drawing: Loading sphere shaders." try: from graphics.drawing.gl_shaders import GLSphereShaderObject drawing_globals.test_sphereShader = GLSphereShaderObject() ##### REVIEW: is this compatible with my refactoring in drawing_globals? # If not, use of Test Graphics Performance command might cause subsequent # bugs in other code. Ideally we'd call the new methods that encapsulate # this, to setup shaders. [bruce 090304 comment] print "test_drawing: Sphere-shader initialization is complete.\n" except: _USE_SHADERS = False print "test_drawing: Exception while loading sphere shaders, will reraise and not try again" raise pass global start_pos, first_time if first_time: # Set up the viewing scale, but then let interactive zooming work. glpane.scale = nSpheres * .6 pass # This same function gets called to set up for drawing, and to draw. if not initOnly: glpane._setup_modelview() glpane._setup_projection() ##glpane._compute_frustum_planes() glClearColor(64.0, 64.0, 64.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ) ##glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) glMatrixMode(GL_MODELVIEW) pass global test_csdl, test_dl, test_dls, test_ibo, test_vbo, test_spheres global test_DrawingSet, test_endpoints, test_Object # See below for test case descriptions and timings on a MacBook Pro. # The Qt event toploop in NE1 tops out at about 60 frames-per-second. # NE1 with test toploop, single CSDL per draw (test case 1) # . 17,424 spheres (132x132, through the color sorter) 4.8 FPS # Russ 080919: More recently, 12.2 FPS. # . Level 2 spheres have 9 triangles x 20 faces, 162 distinct vertices, # visited on the average 2.3 times, giving 384 tri-strip vertices. # . 17,424 spheres is 6.7 million tri-strip vertices. (6,690,816) if testCase == 1: if test_csdl is None: print ("Test case 1, %d^2 spheres\n %s." % (nSpheres, "ColorSorter")) test_csdl = ColorSortedDisplayList() ColorSorter.start(None, test_csdl) drawsphere([0.5, 0.5, 0.5], # color [0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, testloop = nSpheres ) ColorSorter.finish(draw_now = True) pass else: test_csdl.draw() pass # NE1 with test toploop, single display list per draw (test case 2) # . 10,000 spheres (all drawing modes) 17.5 FPS # . 17,424 spheres (132x132, manual display list) 11.1 FPS # . 40,000 spheres (mode 5 - VBO/IBO spheres from DL's) 2.2 FPS # . 40,000 spheres (mode 6 - Sphere shaders from DL's) 2.5 FPS # . 90,000 spheres (all drawing modes) 1.1 FPS elif testCase == 2: if test_dl is None: print ("Test case 2, %d^2 spheres\n %s." % (nSpheres, "One display list calling primitive dl's")) test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) drawsphere_worker_loop(([0.0, 0.0, 0.0], # pos .5, # radius DRAWSPHERE_DETAIL_LEVEL, nSpheres )) glEndList() pass else: glColor3i(127, 127, 127) glCallList(test_dl) pass # NE1 with test toploop, one big chunk VBO/IBO of box quads (test case 3) # . 17,424 spheres (1 box/shader draw call) 43.7 FPS # . 17,424 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 57.7 FPS # . 40,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 56.7 FPS # . 90,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 52.7 FPS # . 160,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 41.4 FPS # . 250,000 spheres (1 box/shader draw call w/ rad/ctrpt attrs) 27.0 FPS elif int(testCase) == 3: doTransforms = False if test_spheres is None: print ("Test case 3, %d^2 spheres\n %s." % (nSpheres, "One big VBO/IBO chunk buffer")) if testCase == 3.1: print ("Sub-test 3.1, animate partial updates.") elif testCase == 3.2: print ("Sub-test 3.2, animate partial updates" + " w/ C per-chunk array buffering.") elif testCase == 3.3: print ("Sub-test 3.3, animate partial updates" + " w/ Python array buffering.") # . 3.4 - Big batch draw, with transforms indexed by IDs added. # (Second FPS number with debug colors in the vertex shader off.) # - 90,000 (300x300) spheres, TEXTURE_XFORMS = True, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 250, 26(29) FPS # - 90,000 (300x300) spheres, N_CONST_XFORMS = 275, 0.3(0.6) FPS # (What happens after 250? CPU usage goes from 40% to 94%.) # -160,000 (400x400) spheres, TEXTURE_XFORMS = True, 26 FPS # -250,000 (500x500) spheres, TEXTURE_XFORMS = True, 26 FPS elif testCase == 3.4: print ("Sub-test 3.4, add transforms indexed by IDs.") from graphics.drawing.gl_shaders import TEXTURE_XFORMS from graphics.drawing.gl_shaders import N_CONST_XFORMS from graphics.drawing.gl_shaders import UNIFORM_XFORMS if TEXTURE_XFORMS: print "Transforms in texture memory." elif UNIFORM_XFORMS: print "%d transforms in uniform memory." % N_CONST_XFORMS pass else: print "transforms not supported, error is likely" doTransforms = True pass centers = [] radius = .5 radii = [] colors = [] if not doTransforms: transformIDs = None else: transformIDs = [] transformChunkID = -1 # Allocate IDs sequentially from 0. # For this test, allow arbitrarily chunking the primitives. primCounter = transformChunkLength transforms = [] # Accumulate transforms as a list of lists. # Initialize transforms with an identity matrix. # Transforms here are lists (or Numpy arrays) of 16 numbers. identity = ([1.0] + 4*[0.0]) * 3 + [1.0] pass for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Transforms go into a texture memory image if needed. # Per-primitive Transform IDs go into an attribute VBO. if doTransforms: primCounter = primCounter + 1 if primCounter >= transformChunkLength: # Start a new chunk, allocating a transform matrix. primCounter = 0 transformChunkID += 1 if 0: # 1 # Debug hack: Label mat[0,0] with the chunk ID. # Vertex shader debug code shows these in blue. # If viewed as geometry, it will be a slight # stretch of the array in the X direction. transforms += [ [1.0+transformChunkID/100.0] + identity[1:]] elif 0: # 1 # Debug hack: Fill mat with mat.element pattern. transforms += [ [transformChunkID + i/100.0 for i in range(16)]] else: transforms += [identity] pass pass # All of the primitives in a chunk have the same ID. transformIDs += [transformChunkID] pass continue continue test_spheres = GLSphereBuffer() test_spheres.addSpheres(centers, radii, colors, transformIDs, None) if doTransforms: print ("%d primitives in %d transform chunks of size <= %d" % (nSpheres * nSpheres, len(transforms), transformChunkLength)) shader = drawing_globals.test_sphereShader shader.setupTransforms(transforms) pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Update portions for animation. pulse = time.time() pulse -= floor(pulse) # 0 to 1 in each second # Test animating updates on 80% of the radii in 45% of the columns. # . 3.1 - Update radii Python array per-column, send to graphics RAM. # - 2,500 (50x50) spheres 55 FPS # - 10,000 (100x100) spheres 35 FPS # - 17,424 (132x132) spheres 22.2 FPS # - 40,000 (200x200) spheres 12.4 FPS # - 90,000 (300x300) spheres 6.0 FPS if testCase == 3.1: # Not buffered, send each column change. radius = .5 margin = nSpheres/10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres radii += 8 * [thisRad-.1 + .1*sin(phase * 2*pi)] continue C_radii = numpy.array(radii, dtype=numpy.float32) offset = x*nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_radii) continue pass # . 3.2 - Numpy buffered in C array, subscript assignments to C. # - 2,500 (50x50) spheres 48 FPS # - 10,000 (100x100) spheres 17.4 FPS # - 17,424 (132x132) spheres 11.2 FPS # - 40,000 (200x200) spheres 5.5 FPS # - 90,000 (300x300) spheres 2.5 FPS elif testCase == 3.2: # Buffered per-chunk at the C array level. radius = .5 margin = nSpheres/10 global C_array if C_array is None: # Replicate. C_array = numpy.zeros((8 * (nSpheres-(2*margin)),), dtype=numpy.float32) pass for x in range(margin, nSpheres, 2): count = 0 for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres C_array[count*8:(count+1)*8] = \ thisRad-.1 + .1*sin(phase * 2*pi) count += 1 continue offset = x*nSpheres + margin test_spheres.radii_vbo.update(offset * 8, C_array) continue pass # . 3.3 - updateRadii in Python array, copy via C to graphics RAM. # - 2,500 (50x50) spheres 57 FPS # - 10,000 (100x100) spheres 32 FPS # - 17,424 (132x132) spheres 20 FPS # - 40,000 (200x200) spheres 10.6 FPS # - 90,000 (300x300) spheres 4.9 FPS elif testCase == 3.3: # Buffered at the Python level, batch the whole-array update. radius = .5 margin = nSpheres/10 for x in range(margin, nSpheres, 2): radii = [] for y in range(margin, nSpheres-margin): t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. # Sphere radii progress from 3/4 to full size. thisRad = radius * (.75 + t*.25) phase = pulse + float(x+y)/nSpheres radii += [thisRad-.1 + .1*sin(phase * 2*pi)] continue test_spheres.updateRadii( # Update, but don't send yet. x*nSpheres + margin, radii, send = False) continue test_spheres.sendRadii() pass # Options: color = [0.0, 1.0, 0.0], transform_id = 1, radius = 1.0 test_spheres.draw() pass # NE1 with test toploop, separate sphere VBO/IBO box/shader draws (test case 4) # . 17,424 spheres (132x132 box/shader draw quads calls) 0.7 FPS elif testCase == 4: if test_ibo is None: print ("Test case 4, %d^2 spheres\n %s." % (nSpheres, "Separate VBO/IBO shader/box buffer sphere calls, no DL")) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject( GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject( GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() pass else: drawing_globals.test_sphereShader.configShader(glpane) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) pass # NE1 with test toploop, # One DL around separate VBO/IBO shader/box buffer sphere calls (test case 5) # . 17,424 spheres (1 box/shader DL draw call) 9.2 FPS elif testCase == 5: if test_dl is None: print ("Test case 5, %d^2 spheres\n %s." % (nSpheres, "One DL around separate VBO/IBO shader/box buffer sphere calls")) # Collect transformed bounding box vertices and offset indices. # Start at the lower-left corner, offset so the whole pattern comes # up centered on the origin. cubeVerts = drawing_globals.shaderCubeVerts cubeIndices = drawing_globals.shaderCubeIndices C_indices = numpy.array(cubeIndices, dtype=numpy.uint32) test_ibo = GLBufferObject( GL_ELEMENT_ARRAY_BUFFER_ARB, C_indices, GL_STATIC_DRAW) test_ibo.unbind() C_verts = numpy.array(cubeVerts, dtype=numpy.float32) test_vbo = GLBufferObject( GL_ARRAY_BUFFER_ARB, C_verts, GL_STATIC_DRAW) test_vbo.unbind() # Wrap a display list around the draws. test_dl = glGenLists(1) glNewList(test_dl, GL_COMPILE_AND_EXECUTE) glEnableClientState(GL_VERTEX_ARRAY) test_vbo.bind() # Vertex data comes from the vbo. glVertexPointer(3, GL_FLOAT, 0, None) drawing_globals.test_sphereShader.setActive(True) glDisable(GL_CULL_FACE) glColor3i(127, 127, 127) test_ibo.bind() # Index data comes from the ibo. for x in range(nSpheres): for y in range(nSpheres): # From drawsphere_worker_loop(). pos = start_pos + (x+x/10+x/100) * V(1, 0, 0) + \ (y+y/10+y/100) * V(0, 1, 0) radius = .5 glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) glScale(radius,radius,radius) glDrawElements(GL_QUADS, 6 * 4, GL_UNSIGNED_INT, None) glPopMatrix() continue continue drawing_globals.test_sphereShader.setActive(False) glEnable(GL_CULL_FACE) test_ibo.unbind() test_vbo.unbind() glDisableClientState(GL_VERTEX_ARRAY) glEndList() else: glColor3i(127, 127, 127) glCallList(test_dl) pass pass # NE1 with test toploop, # N column DL's around VBO/IBO shader/box buffer sphere calls (test case 6) # . 2,500 (50x50) spheres 58 FPS # . 10,000 (100x100) spheres 57 FPS # . 17,424 (132x132) spheres 56 FPS # . 40,000 (200x200) spheres 50 FPS # . 90,000 (300x300) spheres 28 FPS # . 160,000 (400x400) spheres 16.5 FPS # . 250,000 (500x500) spheres 3.2 FPS elif testCase == 6: if test_dls is None: print ("Test case 6, %d^2 spheres\n %s." % (nSpheres, "N col DL's around VBO/IBO shader/box buffer sphere calls")) # Wrap n display lists around the draws (one per column.) test_dls = glGenLists(nSpheres) # Returns ID of first DL in the set. test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] # Each column is relative to its bottom sphere location. Start # at the lower-left corner, offset so the whole pattern comes up # centered on the origin. start_pos = V(0, 0, 0) # So it doesn't get subtracted twice. pos = sphereLoc(x, 0) - V(nSpheres/2.0, nSpheres/2.0, 0) for y in range(nSpheres): centers += [sphereLoc(0, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue test_sphere = GLSphereBuffer() test_sphere.addSpheres(centers, radii, colors, None, None) test_spheres += [test_sphere] glNewList(test_dls + x, GL_COMPILE_AND_EXECUTE) glPushMatrix() glTranslatef(pos[0], pos[1], pos[2]) test_sphere.draw() glPopMatrix() glEndList() continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) # Turn the lights on. for x in range(nSpheres): glCallList(test_dls + x) continue pass pass # NE1 with test toploop, # N column VBO sets of shader/box buffer sphere calls (test case 7) # . 2,500 (50x50) spheres 50 FPS # . 10,000 (100x100) spheres 30.5 FPS # . 17,424 (132x132) spheres 23.5 FPS # . 40,000 (200x200) spheres 16.8 FPS # . 90,000 (300x300) spheres 10.8 FPS # . 160,000 (400x400) spheres 9.1 FPS # . 250,000 (500x500) spheres 7.3 FPS elif testCase == 7: if test_spheres is None: print ("Test case 7, %d^2 spheres\n %s." % (nSpheres, "Per-column VBO/IBO chunk buffers")) test_spheres = [] for x in range(nSpheres): centers = [] radius = .5 radii = [] colors = [] for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.75 + t*.25) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] continue _spheres1 = GLSphereBuffer() _spheres1.addSpheres(centers, radii, colors, None, None) test_spheres += [_spheres1] continue pass else: shader = drawing_globals.test_sphereShader shader.configShader(glpane) for chunk in test_spheres: chunk.draw() pass # NE1 with test toploop, # Short chunk VBO sets of shader/box buffer sphere calls (test case 8) # . 625 (25x25) spheres 30 FPS, 79 chunk buffers of length 8. # . 2,500 (50x50) spheres 13.6 FPS, 313 chunk buffers of length 8. # . 10,000 (100x100) spheres 6.4 FPS, 704 chunk buffers of length 8. # . 10,000 (100x100) spheres 3.3 FPS, 1250 chunk buffers of length 8. # . 17,424 (132x132) spheres 2.1 FPS, 2178 chunk buffers of length 8. # . 2,500 (50x50) spheres 33.5 FPS, 105 chunk buffers of length 24. # . 17,424 (132x132) spheres 5.5 FPS, 726 chunk buffers of length 24. # # Subcase 8.1: CSDLs in a DrawingSet. (Initial pass-through version.) # . 2,500 (50x50) spheres 36.5 FPS, 105 chunk buffers of length 24. # . 5,625 (75x75) spheres 16.1 FPS, 235 chunk buffers of length 24. # . 10,000 (100x100) spheres 0.5 FPS?!, 414 chunk buffers of length 24. # Has to be <= 250 chunks for constant memory transforms? # . 10,000 (100x100) spheres 11.8 FPS, 50 chunk buffers of length 200. # After a minute of startup. # . 10,000 (100x100) spheres 9.3 FPS, 200 chunk buffers of length 50. # After a few minutes of startup. # Subcase 8.2: CSDLs in a DrawingSet with transforms. (Pass-through.) # . 10,000 (100x100) spheres 11.5 FPS, 50 chunk buffers of length 200. # # Subcase 8.1: CSDLs in a DrawingSet. (First HunkBuffer version.) # Measured with auto-rotate on, ignoring startup and occasional outliers. # As before, on a 2 core, 2.4 GHz Intel MacBook Pro with GeForce 8600M GT. # HUNK_SIZE = 10000 # . 2,500 (50x50) spheres 140-200 FPS, 105 chunks of length 24. # . 5,625 (75x75) spheres 155-175 FPS, 235 chunks of length 24. # . 10,000 (100x100) spheres 134-145 FPS, 50 chunks of length 200. # . 10,000 (100x100) spheres 130-143 FPS, 200 chunks of length 50. # . 10,000 (100x100) spheres 131-140 FPS, 1,250 chunks of length 8. # Chunks are gathered into hunk buffers, so no chunk size speed diff. # . 17,424 (132x132) spheres 134-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 131-140 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 20000 # . 17,424 (132x132) spheres 131-140 FPS, 88 chunks of length 200. # . 17,424 (132x132) spheres 130-141 FPS, 2,178 chunks of length 8. # HUNK_SIZE = 10000 # . 40,000 (200x200) spheres 77.5-82.8 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 34.9-42.6 FPS, 11,2500 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # Rotate the sphere-array off-axis 45 degrees to minimize. # (Try adding multi-sampled anti-aliasing, to the drawing test...) # . 160,000 (400x400) spheres 26.4-27.1 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.8-17.1 FPS, 31,250 chunks of length 8. # The pattern is getting too large, far-clipping is setting in. # . 360,000 (600x600) spheres 11.6-11.8 FPS, 45,000 chunks of length 8. # Extreme far-clipping in the drawing test pattern. # HUNK_SIZE = 20000; no significant speed-up. # . 40,000 (200x200) spheres 75.9-81.5 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 41.2-42.4 FPS, 11,250 chunks of length 8. # Spheres are getting down to pixel size, causing moire patterns. # . 160,000 (400x400) spheres 26.5-26.9 FPS, 20,000 chunks of length 8. # . 250,000 (500x500) spheres 16.5-17.1 FPS, 31,250 chunks of length 8. # . 360,000 (600x600) spheres 11.8-12.1 FPS, 45,000 chunks of length 8. # HUNK_SIZE = 5000; no significant slowdown or CPU load difference. # . 40,000 (200x200) spheres 81.0-83.8 FPS, 5,000 chunks of length 8. # . 160,000 (400x400) spheres 27.3-29.4 FPS, 20,000 chunks of length 8. # . 360,000 (600x600) spheres 11.7-12.1 FPS, 45,000 chunks of length 8. # # Retest after updating MacOS to 10.5.5, with TestGraphics, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 68.7-74.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 39.4-42.0 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 24.4-25.2 FPS, 20,000 chunks of length 8. # Retest with glMultiDrawElements drawing indexes in use, HUNK_SIZE = 5000 # . 40,000 (200x200) spheres 52.8-54.4 FPS, 5,000 chunks of length 8. # . 90,000 (300x300) spheres 22.8-23.3 FPS, 11,250 chunks of length 8. # . 160,000 (400x400) spheres 13.5-15.2 FPS, 20,000 chunks of length 8. # # Retest with reworked halo/sphere shader, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 52.8-53.7 FPS, 2,178 chunks of length 8. [60] # . 40,000 (200x200) spheres 29.3-30.4 FPS, 5,000 chunks of length 8.[156] # . 90,000 (300x300) spheres 18.2-19.2 FPS, 11,250 chunks of length 8.[381] # . 160,000 (400x400) spheres 10.2-11.6 FPS, 20,000 chunks of length 8.[747] # Billboard drawing patterns instead of cubes, HUNK_SIZE = 5000 [setup time] # . 17,424 (132x132) spheres 49.7-55.7 FPS, 2,178 chunks of length 8. [35] # . 40,000 (200x200) spheres 39.6-40.8 FPS, 5,000 chunks of length 8. [88] # . 90,000 (300x300) spheres 18.9-19.5 FPS, 11,250 chunks of length 8.[225] # . 160,000 (400x400) spheres 11.2-11.7 FPS, 20,000 chunks of length 8.[476] # elif int(testCase) == 8: doTransforms = False doCylinders = False if test_spheres is None: # Setup. print ("Test case 8, %d^2 primitives\n %s, length %d." % (nSpheres, "Short VBO/IBO chunk buffers", chunkLength)) if testCase == 8.1: print ("Sub-test 8.1, sphere chunks are in CSDL's in a DrawingSet.") test_DrawingSet = DrawingSet() elif testCase == 8.2: print ("Sub-test 8.2, spheres, rotate with TransformControls.") test_DrawingSet = DrawingSet() doTransforms = True elif testCase == 8.3: print ("Sub-test 8.3, cylinder chunks are in CSDL's in a DrawingSet.") test_DrawingSet = DrawingSet() doCylinders = True pass if test_DrawingSet: # note: doesn't happen in test 8.0, which causes a bug then. [bruce 090223 comment] print "constructed test_DrawingSet =", test_DrawingSet if USE_GRAPHICSMODE_DRAW: print ("Use graphicsMode.Draw_model for DrawingSet in paintGL.") pass t1 = time.time() if doTransforms: # Provide several TransformControls to test separate action. global numTCs, TCs numTCs = 3 TCs = [TransformControl() for i in range(numTCs)] pass def primCSDL(centers, radii, colors): if not doTransforms: csdl = ColorSortedDisplayList() # Transformless. else: # Test pattern for TransformControl usage - vertical columns # of TC domains, separated by X coord of first center point. # Chunking will be visible when transforms are changed. xCoord = centers[0][0] - start_pos[0] # Negate centering X. xPercent = (xCoord / (nSpheres + nSpheres/10 + nSpheres/100 - 1 + (nSpheres <= 1))) xTenth = int(xPercent * 10 + .5) csdl = ColorSortedDisplayList(TCs[xTenth % numTCs]) pass # Test selection using the CSDL glname. ColorSorter.pushName(csdl.glname) ColorSorter.start(glpane, csdl) for (color, center, radius) in zip(colors, centers, radii): if not doCylinders: # Through ColorSorter to the sphere primitive buffer... drawsphere(color, center, radius, DRAWSPHERE_DETAIL_LEVEL) else: # Through ColorSorter to cylinder primitive buffer... if not drawing_globals.cylinderShader_available(): print "warning: not cylinderShader_available(), error is likely:" if (True and # Whether to do tapered shader-cylinders. # Display List cylinders don't support taper. glpane.glprefs.cylinderShader_desired()): ###cylRad = (radius/2.0, (.75-radius)/2.0) cylRad = (radius/1.5 - .167, .3 - radius/1.5) else: cylRad = radius/2.0 pass endPt2 = center + V(0.5, 0.0, 0.0) # 0.5, -0.5) drawcylinder(color, center, endPt2, cylRad) global test_endpoints test_endpoints += [(center, endPt2)] pass continue ColorSorter.popName() ColorSorter.finish(draw_now = True) test_DrawingSet.addCSDL(csdl) return csdl if testCase == 8: #bruce 090223 revised to try to avoid traceback def chunkFn(centers, radii, colors): res = GLSphereBuffer() res.addSpheres(centers, radii, colors, None, None) return res pass else: chunkFn = primCSDL pass test_spheres = [] radius = .5 centers = [] radii = [] colors = [] global test_endpoints test_endpoints = [] for x in range(nSpheres): for y in range(nSpheres): centers += [sphereLoc(x, y)] # Sphere radii progress from 3/4 to full size. t = float(x+y)/(nSpheres+nSpheres) # 0 to 1 fraction. thisRad = radius * (.5 + t*.5) radii += [thisRad] # Colors progress from red to blue. colors += [rainbow(t)] # Put out short chunk buffers. if len(centers) >= chunkLength: test_spheres += [ chunkFn(centers, radii, colors) ] centers = [] radii = [] colors = [] continue continue # Remainder fraction buffer. if len(centers): test_spheres += [chunkFn(centers, radii, colors)] pass print "Setup time", time.time() - t1, "seconds." print "%d chunk buffers" % len(test_spheres) pass elif not initOnly: # Run. test_Draw_8x(glpane) pass elif testCase == 100: #bruce 090102 # before making more of these, modularize it somehow from commands.TestGraphics.test_selection_redraw import test_selection_redraw test_class = test_selection_redraw params = ( nSpheres, ) # note: test size is not directly comparable to other tests with same value of nSpheres if test_Object is None \ or not isinstance(test_Object, test_class) \ or test_Object.current_params() != params: # review: same_vals? # Setup. if test_Object: test_Object.destroy() test_Object = test_class(*params) test_Object.activate() print test_Object pass # review: safe to change elif to if? not sure, GL state is only initialized below elif not initOnly: # Run. test_Object.draw_complete() pass pass if not initOnly: glMatrixMode(GL_MODELVIEW) glFlush() pass first_time = False return
def drawHeightfield(color, w, h, textureReady, opacity, SOLID = False, pickCheckOnly = False, hf = None): """ Draw a heighfield using vertex and normal arrays. Optionally, it could be texture mapped. @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick selection purpose. """ if not hf: # Return if heightfield is not provided return glEnable(GL_COLOR_MATERIAL) glEnable(GL_LIGHTING) # Don't use opacity, otherwise the heighfield polygons should be sorted # - something to implement later... ## glColor3v(list(color)) if textureReady: # For texturing, use white color (to be modulated by the texture) glColor3f(1,1,1) else: glColor3fv(list(color)) glPushMatrix() glScalef(w, h, 1.0) if SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) else: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) glDisable(GL_CULL_FACE) if not pickCheckOnly: glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) if textureReady: glEnable(GL_TEXTURE_2D) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_NORMAL_ARRAY) glEnableClientState(GL_TEXTURE_COORD_ARRAY) for tstrip_vert, tstrip_norm, tstrip_tex in hf: glVertexPointer(3, GL_FLOAT, 0, tstrip_vert) glNormalPointer(GL_FLOAT, 0, tstrip_norm) glTexCoordPointer(2, GL_FLOAT, 0, tstrip_tex) glDrawArrays(GL_TRIANGLE_STRIP, 0, len(tstrip_vert)) glDisableClientState(GL_VERTEX_ARRAY) glDisableClientState(GL_NORMAL_ARRAY) glDisableClientState(GL_TEXTURE_COORD_ARRAY) glDisable(GL_COLOR_MATERIAL) if not pickCheckOnly: if textureReady: glDisable(GL_TEXTURE_2D) glDepthMask(GL_TRUE) glEnable(GL_CULL_FACE) if not SOLID: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glPopMatrix() glEnable(GL_LIGHTING) return