def setup(self): self.spot_t = TextureArray((spot_resolution, spot_resolution), max_spots, GL_DEPTH_COMPONENT32F) for i in range(self.spot_t.length): self.spot_fbos.append(RenderTarget(depth_stencil=ArrayLayerTarget(self.spot_t, i))) self.sun_t = TextureArray((sun_resolution, sun_resolution), max_suns, GL_DEPTH_COMPONENT32F) for i in range(self.sun_t.length): self.sun_fbos.append(RenderTarget(depth_stencil=ArrayLayerTarget(self.sun_t, i))) #self.point = TextureArray(spot_resolution, max_points, GL_DEPTH_COMPONENT32F) self.initialized = True
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_main_color = Texture(resolution, GL_RGB32F) self.t_line_color = Texture(resolution, GL_RGB32F) 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_color_accumulate = Texture(resolution, GL_RGB32F) self.fbo_accumulate = RenderTarget([self.t_color_accumulate])
def setup(self): self.spot_depth_t = TextureArray( (self.spot_resolution, self.spot_resolution), self.max_spots, GL_DEPTH_COMPONENT32F) if self.draw_ids: self.spot_id_t = TextureArray( (self.spot_resolution, self.spot_resolution), self.max_spots, GL_R32F) self.spot_fbos = [] for i in range(self.spot_depth_t.length): targets = [None, ArrayLayerTarget(self.spot_id_t, i) ] if self.draw_ids else [None, None] self.spot_fbos.append( RenderTarget(targets, ArrayLayerTarget(self.spot_depth_t, i))) self.sun_depth_t = TextureArray( (self.sun_resolution, self.sun_resolution), self.max_suns * self.sun_cascades, GL_DEPTH_COMPONENT32F) if self.draw_ids: self.sun_id_t = TextureArray( (self.sun_resolution, self.sun_resolution), self.max_suns * self.sun_cascades, GL_R32F) self.sun_fbos = [] for i in range(self.sun_depth_t.length): targets = [None, ArrayLayerTarget(self.sun_id_t, i) ] if self.draw_ids else [None, None] self.sun_fbos.append( RenderTarget(targets, ArrayLayerTarget(self.sun_depth_t, i))) self.point_depth_t = CubeMapArray( (self.point_resolution, self.point_resolution), self.max_points, GL_DEPTH_COMPONENT32F) if self.draw_ids: self.point_id_t = CubeMapArray( (self.point_resolution, self.point_resolution), self.max_points, GL_R32F) self.point_fbos = [] for i in range(self.point_depth_t.length * 6): targets = [None, ArrayLayerTarget(self.point_id_t, i) ] if self.draw_ids else [None, None] self.point_fbos.append( RenderTarget(targets, ArrayLayerTarget(self.point_depth_t, i))) self.initialized = True
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: self.shader = pipeline.compile_shader_from_source(_shader_src) 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 render(self, pipeline, common_buffer, normal_depth_texture, samples, radius): if self.t is None or self.t.resolution != normal_depth_texture.resolution: self.t = Texture(normal_depth_texture.resolution, GL_R32F) self.fbo = RenderTarget([self.t]) if self.shader == None: self.shader = pipeline.compile_shader_from_source(_shader_src) self.shader.textures['IN_NORMAL_DEPTH'] = normal_depth_texture self.shader.uniforms['samples'].set_value(samples) self.shader.uniforms['radius'].set_value(radius) self.shader.bind() common_buffer.bind(self.shader.uniform_blocks['COMMON_UNIFORMS']) pipeline.draw_screen_pass(self.shader, self.fbo) return self.t
class PipelineTest(Pipeline): def __init__(self): super().__init__() self.sampling_grid_size = 2 self.parameters.scene['Preview Samples'] = GLUniform(-1, GL.GL_INT, 4) self.parameters.scene['Render Samples'] = GLUniform(-1, GL.GL_INT, 8) self.parameters.scene['Line Width Max'] = GLUniform(-1, GL.GL_INT, 10) self.parameters.world['Background Color'] = GLUniform( -1, GL_FLOAT_VEC4, (0.5, 0.5, 0.5, 1)) self.default_shader = self.compile_material_from_source( '') #Empty source will force defaults self.composite_depth_shader = self.compile_shader_from_source( _obj_composite_depth) self.common_buffer = Common.CommonBuffer() self.lights_buffer = Lighting.LightsBuffer() self.line_rendering = Line.LineRendering() def compile_material_from_source(self, source, include_paths=[]): source = _NPR_Pipeline_Common + source return { 'PRE_PASS': self.compile_shader_from_source(source, 'COMMON_VERTEX_SHADER', 'PRE_PASS_PIXEL_SHADER', include_paths, ['PRE_PASS']), 'MAIN_PASS': self.compile_shader_from_source(source, 'COMMON_VERTEX_SHADER', 'MAIN_PASS_PIXEL_SHADER', include_paths, ['MAIN_PASS']) } 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_main_color = Texture(resolution, GL_RGB32F) self.t_line_color = Texture(resolution, GL_RGB32F) 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_color_accumulate = Texture(resolution, GL_RGB32F) self.fbo_accumulate = RenderTarget([self.t_color_accumulate]) self.t_composite_depth = Texture(resolution, GL_R32F) self.fbo_composite_depth = RenderTarget([self.t_composite_depth], self.t_depth) def get_samples(self): return Sampling.get_RGSS_samples(self.sampling_grid_size) def do_render(self, resolution, scene, is_final_render, is_new_frame): #SETUP SAMPLING if is_final_render: self.sampling_grid_size = scene.parameters['Render Samples'][0] else: self.sampling_grid_size = scene.parameters['Preview Samples'][0] sample_offset = self.get_samples()[self.sample_count] #SETUP UNIFORM BLOCKS self.common_buffer.load(scene, resolution, sample_offset, self.sample_count) self.lights_buffer.load(scene) UBOS = { 'COMMON_UNIFORMS': self.common_buffer, 'SCENE_LIGHTS': self.lights_buffer } #SETUP PER-OBJECT PARAMETERS for i, obj in enumerate(scene.objects): obj.parameters['MODEL'] = obj.matrix obj.parameters['ID'] = i + 1 #PRE-PASS self.fbo_prepass.clear([(0, 0, 1, 1), 0], 1, 0) self.draw_scene_pass(self.fbo_prepass, scene.objects, 'PRE_PASS', self.default_shader['PRE_PASS'], UBOS) #MAIN-PASS textures = { 'IN_NORMAL_DEPTH': self.t_prepass_normal_depth, 'IN_ID': self.t_prepass_id, } self.fbo_main.clear([ scene.world_parameters['Background Color'], (0, 0, 0, 0), (-1, -1, -1, -1) ]) self.draw_scene_pass(self.fbo_main, scene.objects, 'MAIN_PASS', self.default_shader['MAIN_PASS'], UBOS, {}, textures) composited_line = self.line_rendering.composite_line( scene.parameters['Line Width Max'], self, self.common_buffer, self.t_main_color, self.t_depth, self.t_prepass_id, self.t_line_color, self.t_line_data) # TEMPORAL SUPER-SAMPLING ACCUMULATION # TODO: Should accumulate in display space ??? # https://therealmjp.github.io/posts/msaa-overview/#working-with-hdr-and-tone-mapping self.blend_texture(composited_line, self.fbo_accumulate, 1.0 / (self.sample_count + 1)) #COMPOSITE DEPTH if is_final_render: self.fbo_composite_depth.clear((10.0e+32, 1.0, 1.0, 1.0)) self.draw_scene_pass(self.fbo_composite_depth, scene.objects, None, self.composite_depth_shader, UBOS) return { 'COLOR': self.t_color_accumulate, 'DEPTH': self.t_composite_depth, }
class PipelineTest(Pipeline): def __init__(self): super().__init__() self.sampling_grid_size = 2 self.parameters.world['Background Color'] = GLUniform( -1, GL_FLOAT_VEC4, (0.5, 0.5, 0.5, 1)) self.parameters.scene['Line Width Max'] = GLUniform(-1, GL.GL_INT, 10) self.parameters.scene['Samples Grid Size Preview'] = GLUniform( -1, GL.GL_INT, 4) self.parameters.scene['Samples Grid Size Render'] = GLUniform( -1, GL.GL_INT, 8) self.parameters.scene['Samples Width'] = GLUniform( -1, GL.GL_FLOAT, 1.5) self.parameters.scene[ 'Shadow Cascades Distribution Exponent'] = GLUniform( -1, GL.GL_INT, 21) self.parameters.scene['ShadowMaps Spot Resolution'] = GLUniform( -1, GL.GL_INT, 2048) self.parameters.scene['ShadowMaps Sun Resolution'] = GLUniform( -1, GL.GL_INT, 2048) self.parameters.scene['ShadowMaps Point Resolution'] = GLUniform( -1, GL.GL_INT, 2048) self.common_buffer = Common.CommonBuffer() self.lights_buffer = Lighting.LightsBuffer() self.line_rendering = Line.LineRendering() self.composite_depth = DepthToCompositeDepth.CompositeDepth() def compile_material_from_source(self, source, include_paths=[]): source = _NPR_Pipeline_Common + source return { 'PRE_PASS': self.compile_shader_from_source(source, 'COMMON_VERTEX_SHADER', 'PRE_PASS_PIXEL_SHADER', include_paths, ['PRE_PASS']), 'MAIN_PASS': self.compile_shader_from_source(source, 'COMMON_VERTEX_SHADER', 'MAIN_PASS_PIXEL_SHADER', include_paths, ['MAIN_PASS']) } 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_main_color = Texture(resolution, GL_RGB32F) self.t_line_color = Texture(resolution, GL_RGB32F) 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_color_accumulate = Texture(resolution, GL_RGB32F) self.fbo_accumulate = RenderTarget([self.t_color_accumulate]) def get_samples(self, width=1.0): return Sampling.get_RGSS_samples(self.sampling_grid_size, width) def do_render(self, resolution, scene, is_final_render, is_new_frame): #SETUP SAMPLING if is_final_render: self.sampling_grid_size = scene.parameters[ 'Samples Grid Size Render'][0] else: self.sampling_grid_size = scene.parameters[ 'Samples Grid Size Preview'][0] sample_offset = self.get_samples( scene.parameters['Samples Width'][0])[self.sample_count] #SETUP PER-OBJECT PARAMETERS for i, obj in enumerate(scene.objects): obj.parameters['MODEL'] = obj.matrix obj.parameters['ID'] = i + 1 #SETUP UNIFORM BLOCKS self.common_buffer.load(scene, resolution, sample_offset, self.sample_count) self.lights_buffer.load( scene, self, 'PRE_PASS', scene.parameters['Shadow Cascades Distribution Exponent'][0], scene.parameters['ShadowMaps Spot Resolution'][0], scene.parameters['ShadowMaps Sun Resolution'][0], scene.parameters['ShadowMaps Point Resolution'][0]) UBOS = { 'COMMON_UNIFORMS': self.common_buffer, 'SCENE_LIGHTS': self.lights_buffer } #PRE-PASS self.fbo_prepass.clear([(0, 0, 1, 1), (0, 0, 0, 0)], 1, 0) self.draw_scene_pass(self.fbo_prepass, scene.objects, 'PRE_PASS', self.default_shader['PRE_PASS'], UBOS) #MAIN-PASS textures = { 'IN_NORMAL_DEPTH': self.t_prepass_normal_depth, 'IN_ID': self.t_prepass_id, } callbacks = [lambda shader: self.lights_buffer.shader_callback(shader)] self.fbo_main.clear([ scene.world_parameters['Background Color'], (0, 0, 0, 0), (-1, -1, -1, -1) ]) self.draw_scene_pass(self.fbo_main, scene.objects, 'MAIN_PASS', self.default_shader['MAIN_PASS'], UBOS, {}, textures, callbacks) #COMPOSITE LINE composited_line = self.line_rendering.composite_line( scene.parameters['Line Width Max'], self, self.common_buffer, self.t_main_color, self.t_depth, self.t_prepass_id, self.t_line_color, self.t_line_data) # TEMPORAL SUPER-SAMPLING ACCUMULATION self.blend_texture(composited_line, self.fbo_accumulate, 1.0 / (self.sample_count + 1)) #COMPOSITE DEPTH composite_depth = None if is_final_render: composite_depth = self.composite_depth.render( self, self.common_buffer, self.t_depth) return { 'COLOR': self.t_color_accumulate, 'DEPTH': composite_depth, }
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]) self.t_composite = Texture(color.resolution, GL_RGBA32F) self.fbo_composite = RenderTarget([self.t_composite]) if self.shader == None: self.shader = pipeline.compile_shader_from_source(_shader_src) self.cleanup_shader = pipeline.compile_shader_from_source( _line_cleanup_src) self.composite_shader = pipeline.compile_shader_from_source( _line_composite_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 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) #LINE COMPOSITE self.fbo_composite.clear((0, 0, 0, 0)) self.composite_shader.uniforms['brute_force_range'].set_value( math.ceil(max_width[0] / 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