Esempio n. 1
0
    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

        #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.get_scene(context, depsgraph, self.request_scene_update)
        self.request_scene_update = False
        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.bind_display_space_shader(depsgraph.scene_eval)
        if self.display_draw is None or self.display_draw.resolution != resolution:
            self.display_draw = DisplayDraw(resolution)
        self.display_draw.draw(fbo, render_texture)
        self.unbind_display_space_shader()

        if self.get_pipeline().needs_more_samples():
            self.tag_redraw()

        reset_GL_state()

        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())
Esempio n. 2
0
 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
Esempio n. 3
0
    def setup(self, texture, buffer):
        self.buffer = buffer
        render_target = RenderTarget([texture])
        w,h = texture.resolution
        size = w*h*4*4
        if self.size != size:
            self.size = size
            glDeleteBuffers(1, self.handle)
            glGenBuffers(1, self.handle)
            glBindBuffer(GL_PIXEL_PACK_BUFFER, self.handle[0])
            glBufferData(GL_PIXEL_PACK_BUFFER, size, None, GL_STREAM_READ)
            glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)
        
        render_target.bind()
        GL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0)
        
        glBindBuffer(GL_PIXEL_PACK_BUFFER, self.handle[0])
        GL.glReadPixels(0, 0, w, h, texture.format, texture.data_format, 0)
        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)

        if self.sync:
            glDeleteSync(self.sync)
        self.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)
Esempio n. 4
0
    def render(self, depsgraph):
        Pipeline.MAIN_CONTEXT = False

        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.get_scene(None, depsgraph, True)
        render_textures = None
        while True:
            render_textures = self.get_pipeline().render(
                resolution, scene, True, False)
            if self.get_pipeline().needs_more_samples() == False:
                break

        result = self.begin_result(0, 0, self.size_x, self.size_y)

        if 'COLOR' in render_textures.keys():
            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

        if 'DEPTH' in render_textures.keys():
            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 scene. Otherwise we get memory leaks.
        # Blender never deletes RenderEngine instances ???
        del self.scene
        #Delete the pipeline while we are in the correct OpenGL context
        del self.pipeline
        Pipeline.MAIN_CONTEXT = True
Esempio n. 5
0
 def draw(self, fbo, texture):
     GL.glDisable(GL.GL_DEPTH_TEST)
     GL.glDisable(GL.GL_CULL_FACE)
     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)
Esempio n. 6
0
    def __init__(self, resolution):
        # Generate dummy float image buffer
        self.resolution = resolution
        width, height = resolution

        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)
Esempio n. 7
0
def reset_GL_state():
    GL.glUseProgram(0)
    GL.glBindVertexArray(0)
    GL.glDisable(GL.GL_BLEND)
    GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
    GL.glEnable(GL.GL_DEPTH_TEST)
    GL.glDepthRange(0, 1)
    GL.glDepthFunc(GL.GL_LESS)
    GL.glDisable(GL.GL_CULL_FACE)
    GL.glCullFace(GL.GL_BACK)
    GL.glFrontFace(GL.GL_CCW)
Esempio n. 8
0
 def gl_delete(self):
     GL.glDeleteBuffers(2, self.vertex_buffer)
     GL.glDeleteVertexArrays(1, self.vertex_array)
     GL.glBindTexture(GL.GL_TEXTURE_2D, 0)
Esempio n. 9
0
    def view_draw(self, context, depsgraph):
        if self.bridge is not MaltPipeline.get_bridge():
            #The Bridge has been reset
            self.bridge = MaltPipeline.get_bridge()
            self.bridge_id = self.bridge.get_viewport_id()
            self.request_new_frame = True
            self.request_scene_update = True

        global CAPTURE
        if CAPTURE:
            self.request_new_frame = True

        overrides = []
        if context.space_data.shading.type == 'MATERIAL':
            overrides.append('Preview')

        scene = self.get_scene(context, depsgraph, self.request_scene_update,
                               overrides)
        viewport_resolution = context.region.width, context.region.height
        resolution = viewport_resolution

        resolution_scale = scene.world_parameters['Viewport.Resolution Scale']
        mag_filter = GL.GL_LINEAR
        if resolution_scale != 1.0:
            w, h = resolution
            resolution = round(w * resolution_scale), round(h *
                                                            resolution_scale)
            smooth_interpolation = scene.world_parameters[
                'Viewport.Smooth Interpolation']
            mag_filter = GL.GL_LINEAR if smooth_interpolation else GL.GL_NEAREST

        if self.request_new_frame:
            self.bridge.render(self.bridge_id, resolution, scene,
                               self.request_scene_update, CAPTURE)
            CAPTURE = False
            self.request_new_frame = False
            self.request_scene_update = False

        target_fps = context.preferences.addons[
            'BlenderMalt'].preferences.render_fps_cap
        if target_fps > 0:
            delta_time = time.perf_counter() - self.last_frame_time
            target_delta = 1.0 / target_fps
            if delta_time < target_delta:
                high_res_sleep(target_delta - delta_time)

        self.last_frame_time = time.perf_counter()

        buffers, finished, read_resolution = self.bridge.render_result(
            self.bridge_id)
        pixels = buffers['COLOR']

        if not finished:
            self.tag_redraw()
        if pixels is None or resolution != read_resolution:
            # Only render if resolution is the same as read_resolution.
            # This avoids visual glitches when the viewport is resizing.
            # The alternative would be locking when writing/reading the pixel buffer.
            return

        for region in context.area.regions:
            if region.type == 'UI':
                region.tag_redraw()

        fbo = GL.gl_buffer(GL.GL_INT, 1)
        GL.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, fbo)

        data_format = GL.GL_FLOAT
        texture_format = GL.GL_RGBA32F
        if self.bridge.viewport_bit_depth == 8:
            data_format = GL.GL_UNSIGNED_BYTE
            texture_format = GL.GL_RGBA8
            if GL.glGetInternalformativ(GL.GL_TEXTURE_2D, texture_format,
                                        GL.GL_READ_PIXELS, 1) != GL.GL_ZERO:
                data_format = GL.glGetInternalformativ(
                    GL.GL_TEXTURE_2D, texture_format, GL.GL_TEXTURE_IMAGE_TYPE,
                    1)

        render_texture = Texture(resolution,
                                 texture_format,
                                 data_format,
                                 pixels.buffer(),
                                 mag_filter=mag_filter)

        self.bind_display_space_shader(depsgraph.scene_eval)
        if self.display_draw is None or self.display_draw.resolution != viewport_resolution:
            if self.display_draw:
                self.display_draw.gl_delete()
            self.display_draw = DisplayDraw(viewport_resolution)
        self.display_draw.draw(fbo, render_texture)
        self.unbind_display_space_shader()
Esempio n. 10
0
    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()
        
        if self.bridge is not MaltPipeline.get_bridge():
            #The Bridge has been reset
            self.bridge.free_viewport_id(self.bridge_id)
            self.bridge = MaltPipeline.get_bridge()
            self.bridge_id = self.bridge.get_viewport_id()
            self.request_new_frame = True
            self.request_scene_update = True
        
        overrides = []
        if context.space_data.shading.type == 'MATERIAL':
            overrides.append('Preview')

        scene = self.get_scene(context, depsgraph, self.request_scene_update, overrides)
        resolution = context.region.width, context.region.height

        if self.request_new_frame:
            self.bridge.render(self.bridge_id, resolution, scene, self.request_scene_update)
            self.request_new_frame = False
            self.request_scene_update = False

        buffers, finished, read_resolution = self.bridge.render_result(self.bridge_id)
        pixels = buffers['COLOR']

        if not finished:
            self.tag_redraw()
        if pixels is None or resolution != read_resolution:
            # Only render if resolution is the same as read_resolution.
            # This avoids visual glitches when the viewport is resizing.
            # The alternative would be locking when writing/reading the pixel buffer.
            return

        fbo = GL.gl_buffer(GL.GL_INT, 1)
        GL.glGetIntegerv(GL.GL_FRAMEBUFFER_BINDING, fbo)
        
        render_texture = Texture(resolution, GL.GL_RGBA32F, GL.GL_FLOAT, pixels)
        
        self.bind_display_space_shader(depsgraph.scene_eval)
        if self.display_draw is None or self.display_draw.resolution != resolution:
            if self.display_draw:
                self.display_draw.gl_delete()
            self.display_draw = DisplayDraw(resolution)
        self.display_draw.draw(fbo, render_texture)
        self.unbind_display_space_shader()

        if PROFILE:
            profiler.disable()
            stats = pstats.Stats(profiler, stream=self.profiling_data)
            stats.strip_dirs()
            stats.sort_stats(pstats.SortKey.CUMULATIVE)
            stats.print_stats()
            print('PROFILE BEGIN--------------------------------------')
            print(self.profiling_data.getvalue())
            print('PROFILE END--------------------------------------')