def view_draw(self, context, depsgraph): profiler = cProfile.Profile() global PROFILE if PROFILE: profiler.enable() if self.request_new_frame: self.profiling_data = io.StringIO() # Get viewport resolution resolution = context.region.width, context.region.height def bind_display_shader(): self.bind_display_space_shader(depsgraph.scene_eval) if self.display_draw is None or self.display_draw.resolution != resolution: self.display_draw = DisplayDraw(bind_display_shader, resolution) #Save FBO for later use fbo = GL.gl_buffer(GL.GL_INT, 1) GL.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, fbo) # Generating a VAO before loading/rendering fixes an error where the viewport # freezes in edit mode. Why ??? I have no idea. ¯\_(ツ)_/¯ # TODO: try to load meshes the normal way, without lazy VAO generation. # (Would need a Pipeline refactor) VAO = GL.gl_buffer(GL.GL_INT, 1) GL.glGenVertexArrays(1, VAO) #render scene = self.load_scene(context, depsgraph) render_texture = self.get_pipeline().render( resolution, scene, False, self.request_new_frame)['COLOR'] self.request_new_frame = False if MaltMaterial.INITIALIZED == False: #First viewport render can happen before initialization self.request_new_frame = True #Render to viewport self.display_draw.draw(bind_display_shader, fbo, render_texture) if self.get_pipeline().needs_more_samples(): self.tag_redraw() GL.glDeleteVertexArrays(1, VAO) if PROFILE: profiler.disable() stats = pstats.Stats(profiler, stream=self.profiling_data) stats.strip_dirs() stats.sort_stats(pstats.SortKey.CUMULATIVE) stats.print_stats() if self.get_pipeline().needs_more_samples() == False: PROFILE = False with open(REPORT_PATH, 'w') as file: file.write(self.profiling_data.getvalue())
def __del__(self): try: GL.glDeleteBuffers(2, self.vertex_buffer) GL.glDeleteVertexArrays(1, self.vertex_array) GL.glBindTexture(GL.GL_TEXTURE_2D, 0) except: #TODO: Make sure GL objects are deleted in the correct context pass
def load_mesh(object): m = object.to_mesh() if m is None: return None m.calc_loop_triangles() m.calc_normals_split() #TODO: Blender indexes vertex positions and normals, but not uvs and colors, #we might need to do our own indexing or don't do indexing at all fast_path = False if fast_path: positions = (ctypes.c_float*(len(m.vertices)*3))() m.vertices.foreach_get("co", positions) normals = (ctypes.c_float*(len(m.vertices)*3))() m.vertices.foreach_get("normal", normals) indices = (ctypes.c_uint32*(len(m.loop_triangles)*3))() m.loop_triangles.foreach_get("vertices", indices) return Mesh(positions, indices, normals) else: count = len(m.loops) indices = GL.gl_buffer(GL.GL_UNSIGNED_INT, len(m.loop_triangles)*3) m.loop_triangles.foreach_get("loops",indices) normals = GL.gl_buffer(GL.GL_FLOAT, count*3) m.loops.foreach_get("normal",normals) uvs = [] tangents = [] if len(m.uv_layers) == 0: m.uv_layers.new() #At least 1 UV layer is needed for tangents calculation for i, uv_layer in enumerate(m.uv_layers): uvs.append(GL.gl_buffer(GL.GL_FLOAT, count*2)) uv_layer.data.foreach_get("uv", uvs[i]) try: m.calc_tangents(uvmap=uv_layer.name) except Exception as ex: # TODO: log('DEBUG', "Object :", object.name) log('DEBUG', ex) packed_tangents = [e for l in m.loops for e in (*l.tangent, l.bitangent_sign)] tangents.append(GL.gl_buffer(GL.GL_FLOAT, count*4, packed_tangents)) colors = [] for i, vertex_color in enumerate(m.vertex_colors): colors.append(GL.gl_buffer(GL.GL_FLOAT, count*4)) vertex_color.data.foreach_get("color", colors[i]) pos = [axis for l in m.loops for axis in m.vertices[l.vertex_index].co] positions = GL.gl_buffer(GL.GL_FLOAT, count*3, pos) return Mesh(positions, indices, normals, tangents, uvs, colors)
def view_draw(self, context, depsgraph): # Get viewport resolution resolution = context.region.width, context.region.height def bind_display_shader(): self.bind_display_space_shader(depsgraph.scene_eval) if self.display_draw is None or self.display_draw.resolution != resolution: self.display_draw = DisplayDraw(bind_display_shader, resolution) #Save FBO for later use fbo = GL.gl_buffer(GL.GL_INT, 1) GL.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, fbo) # Generating a VAO before loading/rendering fixes an error where the viewport # freezes in edit mode. Why ??? I have no idea. ¯\_(ツ)_/¯ # TODO: try to load meshes the normal way, without lazy VAO generation. # (Would need a Pipeline refactor) VAO = GL.gl_buffer(GL.GL_INT, 1) GL.glGenVertexArrays(1, VAO) #render scene = self.load_scene(context, depsgraph) render_texture = self.get_pipeline().render( resolution, scene, False, self.request_new_frame)['COLOR'] self.request_new_frame = False if MaltMaterial.INITIALIZED == False: #First viewport render can happen before initialization self.request_new_frame = True #Render to viewport self.display_draw.draw(bind_display_shader, fbo, render_texture) if self.get_pipeline().needs_more_samples(): self.tag_redraw() GL.glDeleteVertexArrays(1, VAO)
def render(self, depsgraph): scene = depsgraph.scene_eval scale = scene.render.resolution_percentage / 100.0 self.size_x = int(scene.render.resolution_x * scale) self.size_y = int(scene.render.resolution_y * scale) resolution = (self.size_x, self.size_y) scene = self.load_scene(None, depsgraph) render_textures = None while True: render_textures = self.get_pipeline().render( resolution, scene, True, False) if self.get_pipeline().needs_more_samples() == False: break render_textures['COLOR'].bind() result = self.begin_result(0, 0, self.size_x, self.size_y) render_textures['COLOR'].bind() gl_pixels = GL.gl_buffer(GL.GL_FLOAT, resolution[0] * resolution[1] * 4) GL.glGetTexImage(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, GL.GL_FLOAT, gl_pixels) it = iter(gl_pixels) pixels = list(zip(it, it, it, it)) #convert from 1D list to list of tuples layer = result.layers[0].passes["Combined"] layer.rect = pixels render_textures['DEPTH'].bind() gl_pixels = GL.gl_buffer(GL.GL_FLOAT, resolution[0] * resolution[1]) GL.glGetTexImage(GL.GL_TEXTURE_2D, 0, GL.GL_RED, GL.GL_FLOAT, gl_pixels) layer = result.layers[0].passes["Depth"] layer.rect.foreach_set(list(gl_pixels)) self.end_result(result) #Delete the pipeline while we are in the correct OpenGL context del self.pipeline
def draw(self, bind_display_shader, fbo, texture): GL.glDisable(GL.GL_DEPTH_TEST) GL.glDisable(GL.GL_CULL_FACE) bind_display_shader() GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo[0]) GL.glActiveTexture(GL.GL_TEXTURE0) texture.bind() GL.glBindVertexArray(self.vertex_array[0]) GL.glDrawArrays(GL.GL_TRIANGLE_FAN, 0, 4) GL.glBindVertexArray(0) GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
def __init__(self, bind_display_shader, resolution): # Generate dummy float image buffer self.resolution = resolution width, height = resolution bind_display_shader() shader_program = GL.gl_buffer(GL.GL_INT, 1) GL.glGetIntegerv(GL.GL_CURRENT_PROGRAM, shader_program) self.vertex_array = GL.gl_buffer(GL.GL_INT, 1) GL.glGenVertexArrays(1, self.vertex_array) GL.glBindVertexArray(self.vertex_array[0]) texturecoord_location = GL.glGetAttribLocation(shader_program[0], "texCoord") position_location = GL.glGetAttribLocation(shader_program[0], "pos") GL.glEnableVertexAttribArray(texturecoord_location) GL.glEnableVertexAttribArray(position_location) position = [0.0, 0.0, width, 0.0, width, height, 0.0, height] position = GL.gl_buffer(GL.GL_FLOAT, len(position), position) texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0] texcoord = GL.gl_buffer(GL.GL_FLOAT, len(texcoord), texcoord) self.vertex_buffer = GL.gl_buffer(GL.GL_INT, 2) GL.glGenBuffers(2, self.vertex_buffer) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vertex_buffer[0]) GL.glBufferData(GL.GL_ARRAY_BUFFER, 32, position, GL.GL_STATIC_DRAW) GL.glVertexAttribPointer(position_location, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, None) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vertex_buffer[1]) GL.glBufferData(GL.GL_ARRAY_BUFFER, 32, texcoord, GL.GL_STATIC_DRAW) GL.glVertexAttribPointer(texturecoord_location, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, None) GL.glBindBuffer(GL.GL_ARRAY_BUFFER, 0) GL.glBindVertexArray(0)