glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None) # set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) glfw.set_scroll_callback(theWindow, window_scroll_callback) vbo = VBO(vertices, 'GL_STATIC_DRAW') vbo.create_buffers() vao = glGenVertexArrays(1) glBindVertexArray(vao) vbo.bind() vbo.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindVertexArray(0) # compile program renderProgram = GLProgram(rayTracingVertexShaderSource, rayTracingFragmentShaderSource) renderProgram.compile_and_link() uniformInfos = [ ('backColor', 'vec3f'), ('ambientColor', 'vec3f'),
glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None) # set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) glfw.set_scroll_callback(theWindow, window_scroll_callback) sphereDataVBO = VBO(sphereData, usage='GL_STATIC_DRAW') sphereDataVBO.create_buffers() sphereVAO = glGenVertexArrays(1) glBindVertexArray(sphereVAO) sphereDataVBO.bind() sphereDataVBO.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float))) glEnableVertexAttribArray(1) sphereDataVBO.unbind()
'Hello Triangle', None, None) # make window the current context glfw.make_context_current(theWindow) if platform.system().lower() != 'darwin': # enable debug output # doesn't seem to work on macOS glEnable(GL_DEBUG_OUTPUT) glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None) # set resizing callback function glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) # create VBO to store vertices verticesVBO = VBO(triangleVertices, usage='GL_STATIC_DRAW') verticesVBO.create_buffers() # create VAO to describe array information triangleVAO = glGenVertexArrays(1) # bind VAO glBindVertexArray(triangleVAO) # bind VBO verticesVBO.bind() # buffer data into OpenGL verticesVBO.copy_data() # configure the fist 3-vector (pos) # arguments: index, size, type, normalized, stride, pointer # the stride is 6 * 4 because there are six floats per vertex, and the size of
glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None) # set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) glfw.set_scroll_callback(theWindow, window_scroll_callback) vertexVBO = VBO(vertices, usage='GL_STATIC_DRAW') vertexVBO.create_buffers() textureVBO = VBO(textureVertices, usage='GL_STATIC_DRAW') textureVBO.create_buffers() frameVAO = glGenVertexArrays(1) glBindVertexArray(frameVAO) vertexVBO.bind() vertexVBO.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindVertexArray(0) textureVAO = glGenVertexArrays(1) glBindVertexArray(textureVAO)
# set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) glfw.set_scroll_callback(theWindow, window_scroll_callback) # create VBOs to store vertices, normals and elements cubeDataVBO = VBO(cubeData, usage='GL_STATIC_DRAW') cubeDataVBO.create_buffers() sphereDataVBO = VBO(sphereData, usage='GL_STATIC_DRAW') sphereDataVBO.create_buffers() # create VAO to describe array information triangleVAO, sphereVAO = glGenVertexArrays(2) # bind VAO glBindVertexArray(triangleVAO) # bind data VBO cubeDataVBO.bind() cubeDataVBO.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
def image_server(evtQueue, resultQueue): # resource-taking objects resObjs = [] # initialize glfw glfw.init() # set glfw config glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) glfw.window_hint(glfw.RESIZABLE, GL_FALSE) if pyPlatform.system().lower() == 'darwin': glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE) # create window theWindow = glfw.create_window(windowSize[0], windowSize[1], 'Spherical Projection', None, None) # make window the current context glfw.make_context_current(theWindow) # enable z-buffer glEnable(GL_DEPTH_TEST) # set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) #glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor #glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) #glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) # glfw.set_scroll_callback(theWindow, window_scroll_callback) vbo = VBO(vertices, 'GL_STATIC_DRAW') vbo.create_buffers() resObjs.append(vbo) vao = glGenVertexArrays(1) glBindVertexArray(vao) vbo.bind() vbo.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glBindVertexArray(0) # compile program renderProgram = GLProgram(rayTracingVertexShaderSource, rayTracingFragmentShaderSource) renderProgram.compile_and_link() uniformInfos = [ ('backColor', 'vec3f'), ('ambientColor', 'vec3f'), ('o_c', 'vec3f'), ('o_p', 'vec3f'), ('x_c', 'vec3f'), ('y_c', 'vec3f'), ('x_p', 'vec3f'), ('y_p', 'vec3f'), ('c_c', 'vec3f'), ('c_p', 'vec3f'), ('winSize', 'vec2f') ] uniforms = create_uniform(renderProgram.get_program_id(), uniformInfos) # keep rendering until the window should be closed while not glfw.window_should_close(theWindow): # set background color glClearColor(*windowBackgroundColor) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) renderProgram.use() # update uniforms o_c, c_c, x_c, y_c = get_camera_vectors(camera) o_p, c_p, x_p, y_p = get_camera_vectors(projector) uniforms['o_c'].update(o_c) uniforms['x_c'].update(x_c) uniforms['y_c'].update(y_c) uniforms['c_c'].update(c_c) uniforms['o_p'].update(o_p) uniforms['x_p'].update(x_p) uniforms['y_p'].update(y_p) uniforms['c_p'].update(c_p) uniforms['backColor'].update(backColor) uniforms['ambientColor'].update(ambientColor) uniforms['winSize'].update(windowSize.astype(np.float32)) try: newImage = evtQueue.get(timeout=0.05) except Exception as e: # tell glfw to poll and process window events glfw.poll_events() # swap frame buffer glfw.swap_buffers(theWindow) continue texture = create_texture(newImage) glBindVertexArray(vao) glActiveTexture(GL_TEXTURE0) texture.bind() glDrawArrays(GL_TRIANGLES, 0, 6) texture.unbind() glBindVertexArray(0) texture.delete() # respond key press keyboard_respond_func() # tell glfw to poll and process window events glfw.poll_events() # swap frame buffer glfw.swap_buffers(theWindow) result = get_screenshot(windowSize) resultQueue.put(result) for obj in resObjs: obj.delete() # terminate glfw glfw.terminate()
glDebugMessageCallback(GLDEBUGPROC(debug_message_callback), None) # set resizing callback function # glfw.set_framebuffer_size_callback(theWindow, window_resize_callback) glfw.set_key_callback(theWindow, window_keypress_callback) # disable cursor glfw.set_input_mode(theWindow, glfw.CURSOR, glfw.CURSOR_DISABLED) glfw.set_cursor_pos_callback(theWindow, window_cursor_callback) # initialize cursor position cursorPos = glfw.get_cursor_pos(theWindow) glfw.set_scroll_callback(theWindow, window_scroll_callback) gridVBO = VBO(gridArray, usage='GL_DYNAMIC_DRAW') gridVBO.create_buffers() gridEBO = VBO(elementArray, usage='GL_STATIC_DRAW', target='GL_ELEMENT_ARRAY_BUFFER') gridEBO.create_buffers() gridVAO = glGenVertexArrays(1) glBindVertexArray(gridVAO) gridVBO.bind() gridVBO.copy_data() gridEBO.bind() gridEBO.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0))
class TextDrawer: def __init__(self): self.face = None self.textures = dict() # compile rendering program self.renderProgram = GLProgram(_textVertexShaderSource, _textFragmentShaderSource) self.renderProgram.compile_and_link() # make projection uniform self.projectionUniform = GLUniform(self.renderProgram.get_program_id(), 'projection', 'mat4f') self.textColorUniform = GLUniform(self.renderProgram.get_program_id(), 'textColor', 'vec3f') self.textureSizeUniform = GLUniform( self.renderProgram.get_program_id(), 'textureSize', 'vec2f') # create rendering buffer self.vbo = VBO(_get_rendering_buffer(0, 0, 0, 0)) self.vbo.create_buffers() self.vboId = glGenBuffers(1) # initialize VAO self.vao = glGenVertexArrays(1) glBindVertexArray(self.vao) glBindBuffer(GL_ARRAY_BUFFER, self.vboId) self.vbo.bind() self.vbo.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float))) glEnableVertexAttribArray(1) # self.vbo.unbind() glBindVertexArray(0) self.zNear = -1.0 self.zFar = 1.0 def delete(self): self.textures.clear() self.face = None self.renderProgram.delete() self.projectionUniform = None self.textColorUniform = None self.textureSizeUniform = None self.vbo.delete() glDeleteVertexArrays(1, [self.vao]) def load_font(self, fontFilename, fontSize): assert os.path.exists(fontFilename) self.textures.clear() self.face = ft.Face(fontFilename) self.face.set_char_size(fontSize) # load all ASCII characters for i in range(128): self.load_character(chr(i)) def load_character(self, character): assert self.face is not None assert len(character) == 1 if character not in self.textures: # load glyph in freetype self.face.load_char(character) ftBitmap = self.face.glyph.bitmap height, width = ftBitmap.rows, ftBitmap.width bitmap = np.array(ftBitmap.buffer, dtype=np.uint8).reshape( (height, width)) # create texture texture = _create_text_texture(bitmap) # add texture object to the dictionary characterSlot = CharacterSlot(texture, self.face.glyph) self.textures[character] = characterSlot def get_character(self, ch): if ch not in self.textures: self.load_character(ch) return self.textures[ch] def _draw_text(self, text, textPos, windowSize, scale, linespread, foreColor): if len(text) == 0: return blendEnabled = glIsEnabled(GL_BLEND) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) self.renderProgram.use() glBindVertexArray(self.vao) glActiveTexture(GL_TEXTURE0) foreColor = np.asarray(foreColor, np.float32) self.textColorUniform.update(foreColor) projectionMat = orthographic_projection(0.0, windowSize[0], 0.0, windowSize[1], self.zNear, self.zFar) self.projectionUniform.update(projectionMat) lineY = textPos[1] nowX = textPos[0] # split text into lines lines = text.split('\n') for line in lines: if len(line) > 0: # analyze this line bearings = [] for ch in line: charSlot = self.get_character(ch) bearings.append(charSlot.bearing[1] * scale[1]) maxBearings = max(bearings) for ch in line: charSlot = self.get_character(ch) xpos = nowX + charSlot.bearing[0] * scale[0] yLowerd = (maxBearings - charSlot.bearing[1] * scale[1]) ypos = lineY - yLowerd w = charSlot.textureSize[0] * scale[0] h = charSlot.textureSize[1] * scale[1] self.textureSizeUniform.update(np.array((w, h), np.float32)) charSlot.texture.bind() self.vbo.bind() self.vbo.set_array( _get_rendering_buffer(xpos, ypos, w, h, 0.999)) self.vbo.copy_data() self.vbo.unbind() glDrawArrays(GL_TRIANGLES, 0, 6) charSlot.texture.unbind() # the advance is number of 1/64 pixels nowX += (charSlot.advance / 64.0) * scale[0] nowX = textPos[0] yOffset = self.get_character( 'X').textureSize[1] * scale[1] * linespread lineY -= yOffset glBindVertexArray(0) if not blendEnabled: glDisable(GL_BLEND) def draw_text(self, text, textPos, windowSize, color=(1.0, 1.0, 1.0), scale=(1.0, 1.0), linespread=1.5): return self._draw_text(text, textPos, windowSize, scale, linespread, color)
class TextDrawer_Outlined: def __init__(self): self.face = None self.stroker = None self.foreTextures = dict() self.backTextures = dict() # compile rendering program self.renderProgram = GLProgram(_textVertexShaderSource, _textFragmentShaderSource) self.renderProgram.compile_and_link() # make projection uniform self.projectionUniform = GLUniform(self.renderProgram.get_program_id(), 'projection', 'mat4f') self.textColorUniform = GLUniform(self.renderProgram.get_program_id(), 'textColor', 'vec3f') self.textureSizeUniform = GLUniform( self.renderProgram.get_program_id(), 'textureSize', 'vec2f') # create rendering buffer self.vbo = VBO(_get_rendering_buffer(0, 0, 0, 0)) self.vbo.create_buffers() self.vboId = glGenBuffers(1) # initialize VAO self.vao = glGenVertexArrays(1) glBindVertexArray(self.vao) glBindBuffer(GL_ARRAY_BUFFER, self.vboId) self.vbo.bind() self.vbo.copy_data() glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(0)) glEnableVertexAttribArray(0) glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 5 * ctypes.sizeof(ctypes.c_float), ctypes.c_void_p(3 * ctypes.sizeof(ctypes.c_float))) glEnableVertexAttribArray(1) # self.vbo.unbind() glBindVertexArray(0) self.zNear = -1.0 self.zFar = 1.0 def delete(self): self.foreTextures.clear() self.backTextures.clear() self.face = None self.stroker = None self.renderProgram.delete() self.projectionUniform = None self.textColorUniform = None self.textureSizeUniform = None self.vbo.delete() glDeleteVertexArrays(1, [self.vao]) def load_font(self, fontFilename, fontSize, outlineSize=2 * 64): assert os.path.exists(fontFilename) self.foreTextures.clear() self.backTextures.clear() self.face = ft.Face(fontFilename) self.face.set_char_size(fontSize) self.outlineSize = outlineSize self.stroker = ft.Stroker() self.stroker.set(outlineSize, ft.FT_STROKER_LINECAPS['FT_STROKER_LINECAP_ROUND'], ft.FT_STROKER_LINEJOINS['FT_STROKER_LINEJOIN_ROUND'], 0) # load all ASCII characters for i in range(128): self.load_character(chr(i)) def load_character(self, character): assert self.face is not None assert len(character) == 1 if character not in self.foreTextures: # load background glyph # the render option will lead to an outline glyph (not rendered) self.face.load_char(character, ft.FT_LOAD_FLAGS['FT_LOAD_DEFAULT']) backGlyph = ft.FT_Glyph() ft.FT_Get_Glyph(self.face.glyph._FT_GlyphSlot, ft.byref(backGlyph)) backGlyph = ft.Glyph(backGlyph) # add border to the glyph error = ft.FT_Glyph_StrokeBorder(ft.byref(backGlyph._FT_Glyph), self.stroker._FT_Stroker, False, False) if error: raise ft.FT_Exception(error) # the render option will lead to a rendered glyph backBitmapGlyph = backGlyph.to_bitmap( ft.FT_RENDER_MODES['FT_RENDER_MODE_NORMAL'], 0) backBitmap = backBitmapGlyph.bitmap backHeight, backWidth = backBitmap.rows, backBitmap.width backBitmap = np.array(backBitmap.buffer, dtype=np.uint8).reshape( (backHeight, backWidth)) backTexture = _create_text_texture(backBitmap) backSlot = CharacterSlot(backTexture, backBitmapGlyph) self.backTextures[character] = backSlot # load foreground glyph self.face.load_char(character, ft.FT_LOAD_FLAGS['FT_LOAD_RENDER']) foreBitmap = self.face.glyph.bitmap foreHeight, foreWidth = foreBitmap.rows, foreBitmap.width foreBitmap = np.array(foreBitmap.buffer, dtype=np.uint8).reshape( (foreHeight, foreWidth)) foreTexture = _create_text_texture(foreBitmap) foreSlot = CharacterSlot(foreTexture, self.face.glyph) self.foreTextures[character] = foreSlot def get_character(self, ch): if ch not in self.foreTextures: self.load_character(ch) return (self.foreTextures[ch], self.backTextures[ch]) def _draw_text(self, text, textPos, windowSize, scale, linespread, foreColor, backColor): if len(text) == 0: return blendEnabled = glIsEnabled(GL_BLEND) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) self.renderProgram.use() glBindVertexArray(self.vao) glActiveTexture(GL_TEXTURE0) foreColor = np.asarray(foreColor, np.float32) backColor = np.asarray(backColor, np.float32) projectionMat = orthographic_projection(0.0, windowSize[0], 0.0, windowSize[1], self.zNear, self.zFar) self.projectionUniform.update(projectionMat) lineY = textPos[1] nowX = textPos[0] # split text into lines lines = text.split('\n') for line in lines: if len(line) > 0: # analyze this line bearings = [] for ch in line: _, backSlot = self.get_character(ch) bearings.append(backSlot.bearing) minBearings_X = min(zip(*bearings), key=operator.itemgetter(0))[0] * scale[0] maxBearings_Y = max(zip(*bearings), key=operator.itemgetter(1))[1] * scale[1] nowX = -minBearings_X for ch in line: foreSlot, backSlot = self.get_character(ch) # draw the background xpos = nowX + backSlot.bearing[0] * scale[0] yLowerd = (maxBearings_Y - backSlot.bearing[1] * scale[1]) ypos = lineY - yLowerd w = backSlot.textureSize[0] * scale[0] h = backSlot.textureSize[1] * scale[1] self.textureSizeUniform.update(np.array((w, h), np.float32)) backSlot.texture.bind() self.textColorUniform.update(backColor) self.vbo.bind() self.vbo.set_array( _get_rendering_buffer(xpos, ypos, w, h, 0.99)) self.vbo.copy_data() self.vbo.unbind() glDrawArrays(GL_TRIANGLES, 0, 6) backSlot.texture.unbind() # draw the foreground xpos = nowX + foreSlot.bearing[0] * scale[0] yLowerd = (maxBearings_Y - foreSlot.bearing[1] * scale[1]) ypos = lineY - yLowerd w = foreSlot.textureSize[0] * scale[0] h = foreSlot.textureSize[1] * scale[1] foreSlot.texture.bind() self.textColorUniform.update(foreColor) self.vbo.bind() # the foreground is set closer to the screen so that it # is rendered above the background self.vbo.set_array( _get_rendering_buffer(xpos, ypos, w, h, 0.999)) self.vbo.copy_data() self.vbo.unbind() glDrawArrays(GL_TRIANGLES, 0, 6) foreSlot.texture.unbind() # the advance is number of 1/64 pixels nowX += ((foreSlot.advance + 2.0 * self.outlineSize) / 64.0) * scale[0] yOffset = self.get_character( 'X')[1].textureSize[1] * scale[1] * linespread lineY -= yOffset glBindVertexArray(0) if not blendEnabled: glDisable(GL_BLEND) def draw_text(self, text, textPos, windowSize, foreColor=(1.0, 1.0, 1.0), backColor=(0.0, 0.0, 0.0), scale=(1.0, 1.0), linespread=1.5): return self._draw_text(text, textPos, windowSize, scale, linespread, foreColor, backColor)