def setup(self, new_buffers, resolution, scene, scene_update, renderdoc_capture): if self.resolution != resolution: self.resolution = resolution self.pbos_inactive.extend(self.pbos_active) self.pbos_active = [] assert (new_buffers is not None) if self.bit_depth == 8: optimal_format = GL_UNSIGNED_BYTE if glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_READ_PIXELS, 1) != GL_ZERO: optimal_format = glGetInternalformativ( GL_TEXTURE_2D, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1) try: self.final_texture = Texture(resolution, GL_RGBA8, optimal_format, pixel_format=GL_RGBA) except: # Fallback to unsigned byte, just in case self.final_texture = Texture(resolution, GL_RGBA8, GL_UNSIGNED_BYTE, pixel_format=GL_RGBA) self.final_texture.channel_size = 1 self.final_target = RenderTarget([self.final_texture]) if new_buffers: self.buffers = new_buffers self.sample_index = 0 self.is_new_frame = True self.needs_more_samples = True self.renderdoc_capture = renderdoc_capture self.stat_time_start = time.perf_counter() if scene_update or self.scene is None: for key, proxy in scene.proxys.items(): proxy.resolve() for obj in scene.objects: obj.matrix = (ctypes.c_float * 16)(*obj.matrix) scene.batches = self.pipeline.build_scene_batches(scene.objects) self.scene = scene else: self.scene.camera = scene.camera self.scene.time = scene.time self.scene.frame = scene.frame
def setup_render_targets(self, resolution, custom_io): self.opaque_targets = {} self.transparent_targets = {} self.color_targets = {} for io in custom_io: if io['io'] == 'out' and io['type'] == 'Texture':#TODO self.opaque_targets[io['name']] = Texture(resolution, GL.GL_RGBA16F) self.transparent_targets[io['name']] = Texture(resolution, GL.GL_RGBA16F) self.color_targets[io['name']] = Texture(resolution, GL.GL_RGBA16F) self.fbo_opaque = RenderTarget([*self.opaque_targets.values()]) self.fbo_transparent = RenderTarget([*self.transparent_targets.values()]) self.fbo_color = RenderTarget([*self.color_targets.values()])
def execute(self, parameters): from Malt.GL import GL from Malt.GL.Texture import Texture from Malt.GL.RenderTarget import RenderTarget if self.pipeline.resolution != self.resolution: for i in range(4): #TODO: Doesn't work with GL_RGBA? self.texture_targets[i] = Texture(self.pipeline.resolution, GL.GL_RGBA16F) self.render_target = RenderTarget(self.texture_targets) self.resolution = self.pipeline.resolution self.render_target.clear([(0,0,0,0)]*4) global _UNPACK_SHADER if _UNPACK_SHADER is None: _UNPACK_SHADER = self.pipeline.compile_shader_from_source(_UNPACK_SRC) _UNPACK_SHADER.textures['IN_PACKED'] = parameters['Packed Texture'] self.pipeline.draw_screen_pass(_UNPACK_SHADER, self.render_target, blend = False) parameters['A'] = self.texture_targets[0] parameters['B'] = self.texture_targets[1] parameters['C'] = self.texture_targets[2] parameters['D'] = self.texture_targets[3]
def execute(self, parameters): inputs = parameters['IN'] outputs = parameters['OUT'] material = parameters['PASS_MATERIAL'] custom_io = parameters['CUSTOM_IO'] if self.pipeline.resolution != self.resolution or self.custom_io != custom_io: self.texture_targets = {} for io in custom_io: if io['io'] == 'out': if io['type'] == 'Texture':#TODO self.texture_targets[io['name']] = Texture(self.pipeline.resolution, GL.GL_RGBA16F) self.render_target = RenderTarget([*self.texture_targets.values()]) self.resolution = self.pipeline.resolution self.custom_io = custom_io self.render_target.clear([(0,0,0,0)]*len(self.texture_targets)) if material and material.shader and 'SHADER' in material.shader: shader = material.shader['SHADER'] for io in custom_io: if io['io'] == 'in': if io['type'] == 'Texture':#TODO from Malt.SourceTranspiler import GLSLTranspiler glsl_name = GLSLTranspiler.custom_io_reference('IN', 'SCREEN_SHADER', io['name']) shader.textures[glsl_name] = inputs[io['name']] self.pipeline.common_buffer.shader_callback(shader) shader.uniforms['RENDER_LAYER_MODE'].set_value(False) self.pipeline.draw_screen_pass(shader, self.render_target) for io in custom_io: if io['io'] == 'out': if io['type'] == 'Texture':#TODO outputs[io['name']] = self.texture_targets[io['name']]
def setup_render_targets(self, resolution, t_depth, custom_io): self.custom_targets = {} for io in custom_io: if io['io'] == 'out' and io['type'] == 'Texture': #TODO self.custom_targets[io['name']] = Texture( resolution, GL.GL_RGBA16F) self.t_depth = t_depth self.fbo = RenderTarget([*self.custom_targets.values()], self.t_depth)
def do_render(self, resolution, scene, is_final_render, is_new_frame): #SETUP SAMPLING if self.sampling_grid_size != scene.world_parameters['Samples.Grid Size']: self.sampling_grid_size = scene.world_parameters['Samples.Grid Size'] self.samples = None self.is_new_frame = is_new_frame sample_offset = self.get_sample(scene.world_parameters['Samples.Width']) opaque_batches, transparent_batches = self.get_scene_batches(scene) self.common_buffer.load(scene, resolution, sample_offset, self.sample_count) scene.shader_resources = { 'COMMON_UNIFORMS' : self.common_buffer } result = { 'COLOR': None, 'DEPTH': None, } graph = scene.world_parameters['Render'] if graph: IN = {'Scene' : scene} OUT = {'Color' : None} self.graphs['Render'].run_source(self, graph['source'], graph['parameters'], IN, OUT) result = OUT result['COLOR'] = result['Color'] result['DEPTH'] = result['Depth'] #COMPOSITE DEPTH if is_final_render and result['DEPTH'] is None: if self.sample_count == len(self.samples) - 1: normal_depth = Texture(resolution, GL_RGBA32F) target = RenderTarget([normal_depth], Texture(resolution, GL_DEPTH_COMPONENT32F)) target.clear([(0,0,1,1)], 1) self.common_buffer.load(scene, resolution) self.draw_scene_pass(target, opaque_batches, 'PRE_PASS', self.default_shader, scene.shader_resources) result['DEPTH'] = self.composite_depth.render(self, self.common_buffer, normal_depth, depth_channel=3) return result
def execute(self, parameters): inputs = parameters['IN'] outputs = parameters['OUT'] material = parameters['PASS_MATERIAL'] custom_io = parameters['CUSTOM_IO'] deferred_mode = inputs['Layer Only'] scene = inputs['Scene'] t_normal_depth = inputs['Normal Depth'] t_id = inputs['ID'] shader_resources = {} if scene: shader_resources = scene.shader_resources.copy() if t_normal_depth: shader_resources['IN_NORMAL_DEPTH'] = TextureShaderResource('IN_NORMAL_DEPTH', t_normal_depth) if t_id: shader_resources['IN_ID'] = TextureShaderResource('IN_ID', t_id) if self.pipeline.resolution != self.resolution or self.custom_io != custom_io: self.texture_targets = {} for io in custom_io: if io['io'] == 'out': if io['type'] == 'Texture':#TODO self.texture_targets[io['name']] = Texture(self.pipeline.resolution, GL.GL_RGBA16F) self.render_target = RenderTarget([*self.texture_targets.values()]) self.resolution = self.pipeline.resolution self.custom_io = custom_io self.render_target.clear([(0,0,0,0)]*len(self.texture_targets)) if material and material.shader and 'SHADER' in material.shader: shader = material.shader['SHADER'] for io in custom_io: if io['io'] == 'in': if io['type'] == 'Texture':#TODO from Malt.SourceTranspiler import GLSLTranspiler glsl_name = GLSLTranspiler.custom_io_reference('IN', 'SCREEN_SHADER', io['name']) shader.textures[glsl_name] = inputs[io['name']] self.pipeline.common_buffer.bind(shader.uniform_blocks['COMMON_UNIFORMS']) for resource in shader_resources.values(): resource.shader_callback(shader) shader.uniforms['RENDER_LAYER_MODE'].set_value(True) shader.uniforms['DEFERRED_MODE'].set_value(deferred_mode) self.pipeline.draw_screen_pass(shader, self.render_target) for io in custom_io: if io['io'] == 'out': if io['type'] == 'Texture':#TODO outputs[io['name']] = self.texture_targets[io['name']]
def render(self, pipeline, common_buffer, depth_texture, depth_channel=0): if self.t is None or self.t.resolution != depth_texture.resolution: self.t = Texture(depth_texture.resolution, GL_R32F) self.fbo = RenderTarget([self.t]) if self.shader == None: global _SHADER if _SHADER is None: _SHADER = pipeline.compile_shader_from_source(_shader_src) self.shader = _SHADER self.shader.textures['DEPTH_TEXTURE'] = depth_texture self.shader.uniforms['DEPTH_CHANNEL'].set_value(depth_channel) common_buffer.shader_callback(self.shader) pipeline.draw_screen_pass(self.shader, self.fbo) return self.t
def render(self, pipeline, common_buffer, depth_texture): if self.t is None or self.t.resolution != depth_texture.resolution: self.t = Texture(depth_texture.resolution, GL_R32F) self.fbo = RenderTarget([self.t]) if self.shader == None: global _SHADER if _SHADER is None: _SHADER = pipeline.compile_shader_from_source(_shader_src) self.shader = _SHADER self.shader.textures['DEPTH_TEXTURE'] = depth_texture self.shader.bind() common_buffer.bind(self.shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.draw_screen_pass(self.shader, self.fbo) return self.t
def setup_render_targets(self, resolution, custom_io): self.t_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.t_normal_depth = Texture(resolution, GL_RGBA32F) self.t_id = Texture(resolution, GL_RGBA16UI, min_filter=GL_NEAREST, mag_filter=GL_NEAREST) self.custom_targets = {} for io in custom_io: if io['io'] == 'out' and io['type'] == 'Texture':#TODO self.custom_targets[io['name']] = Texture(resolution, GL.GL_RGBA16F) self.fbo = RenderTarget([self.t_normal_depth, self.t_id, *self.custom_targets.values()], self.t_depth) self.t_last_layer_id = Texture(resolution, GL_R16UI, min_filter=GL_NEAREST, mag_filter=GL_NEAREST) self.fbo_last_layer_id = RenderTarget([self.t_last_layer_id]) self.t_opaque_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.fbo_opaque_depth = RenderTarget([], self.t_opaque_depth) self.t_transparent_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.fbo_transparent_depth = RenderTarget([], self.t_transparent_depth)
def setup_render_targets(self, resolution): self.t_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.t_prepass_normal_depth = Texture(resolution, GL_RGBA32F) self.t_prepass_id = Texture(resolution, GL_R32F) self.fbo_prepass = RenderTarget( [self.t_prepass_normal_depth, self.t_prepass_id], self.t_depth) self.t_last_layer_id = Texture(resolution, GL_R32F) self.fbo_last_layer_id = RenderTarget([self.t_last_layer_id]) self.t_main_color = Texture(resolution, GL_RGBA32F) self.t_line_color = Texture(resolution, GL_RGBA32F) self.t_line_data = Texture(resolution, GL_RGB32F) self.fbo_main = RenderTarget( [self.t_main_color, self.t_line_color, self.t_line_data], self.t_depth) self.t_opaque_color = Texture(resolution, GL_RGB32F) self.t_opaque_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.fbo_opaque = RenderTarget([self.t_opaque_color], self.t_opaque_depth) self.t_transparent_color = Texture(resolution, GL_RGBA32F) self.t_transparent_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.fbo_transparent = RenderTarget([self.t_transparent_color], self.t_transparent_depth) self.t_color = Texture(resolution, GL_RGBA32F) self.fbo_color = RenderTarget([self.t_color]) self.t_color_accumulate = Texture(resolution, GL_RGB32F) self.fbo_accumulate = RenderTarget([self.t_color_accumulate])
def setup_render_targets(self, resolution): self.t_color = Texture(resolution, GL_RGBA16F) self.fbo = RenderTarget([self.t_color])
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()
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--------------------------------------')
def setup_render_targets(self, resolution): self.t_depth = Texture(resolution, GL_DEPTH_COMPONENT32F) self.t_main_color = Texture(resolution, GL_RGBA32F) self.fbo_main = RenderTarget([self.t_main_color], self.t_depth)
def setup_render_targets(self, resolution): super().setup_render_targets(resolution) self.t_postpro = Texture(resolution, GL_RGBA32F) self.fbo_postpro = RenderTarget([self.t_postpro])
def composite_line(self, max_width, pipeline, common_buffer, color, depth, id_texture, line_color, line_data): ''' if self.t_a is None or self.t_a.resolution != color.resolution: self.t_a = Texture(color.resolution, GL_RGBA32F) self.fbo_a = RenderTarget([self.t_a]) self.t_b = Texture(color.resolution, GL_RGBA32F) self.fbo_b = RenderTarget([self.t_b]) if self.shader is None: self.shader = pipeline.compile_shader_from_source(_shader_src) self.cleanup_shader = pipeline.compile_shader_from_source(_line_cleanup_src) #CLEANUP LINE #(Try to workaround numerical stability issues, disabled for now) cleanup = False if cleanup: self.fbo_composite.clear([(0,0,0,0)]) self.cleanup_shader.textures['line_data_texture'] = line_data self.cleanup_shader.bind() common_buffer.bind(self.cleanup_shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.draw_screen_pass(self.cleanup_shader, self.fbo_composite) line_data = self.fbo_composite.targets[0] #JUMP FLOOD #Disabled since we moved back to brute-force line rendering jump_flood = False if jump_flood: jump_flood_max_width = max(line_data.resolution[0], line_data.resolution[1]) steps = [] width = 1 while width < jump_flood_max_width: steps.append(width) width*=2 steps.reverse() self.fbo_a.clear([(-1,-1,-1,-1)]) self.fbo_b.clear([(-1,-1,-1,-1)]) read = line_data write = self.fbo_b for i, step in enumerate(steps): if i > 0: if i % 2 == 0: read = self.t_a write = self.fbo_b else: read = self.t_b write = self.fbo_a self.shader.textures['input_texture'] = read self.shader.uniforms['width'].set_value(step) self.shader.bind() common_buffer.bind(self.shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.draw_screen_pass(self.shader, write) ''' if self.t_composite is None or self.t_composite.resolution != color.resolution: self.t_composite = Texture(color.resolution, GL_RGBA32F) self.fbo_composite = RenderTarget([self.t_composite]) if self.composite_shader is None: global _LINE_COMPOSITE_SHADER if _LINE_COMPOSITE_SHADER is None: _LINE_COMPOSITE_SHADER = pipeline.compile_shader_from_source( _line_composite_src) self.composite_shader = _LINE_COMPOSITE_SHADER #LINE COMPOSITE self.fbo_composite.clear([(0, 0, 0, 0)]) self.composite_shader.uniforms['brute_force_range'].set_value( math.ceil(max_width / 2)) self.composite_shader.textures['color_texture'] = color self.composite_shader.textures['depth_texture'] = depth self.composite_shader.textures['id_texture'] = id_texture self.composite_shader.textures['line_color_texture'] = line_color self.composite_shader.textures['line_data_texture'] = line_data #self.composite_shader.textures['line_distance_field_texture'] = write.targets[0] self.composite_shader.bind() common_buffer.bind( self.composite_shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.draw_screen_pass(self.composite_shader, self.fbo_composite) return self.t_composite