def _rtt_load_attachment(cfg): quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) background = ngl.Render(quad, program) background.update_frag_resources(color=ngl.UniformVec4(value=COLORS['white'])) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['orange'])) texture = ngl.Texture2D(width=16, height=16) rtt = ngl.RenderToTexture(render, [texture]) texture_noop = ngl.Texture2D(width=16, height=16) rtt_noop = ngl.RenderToTexture(render, [texture_noop]) quad = ngl.Quad((0, 0, 0), (1, 0, 0), (0, 1, 0)) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) foreground = ngl.Render(quad, program) foreground.update_frag_resources(tex0=texture) return ngl.Group(children=(background, rtt, rtt_noop, foreground))
def parallel_playback(cfg, fast=True, segment_time=2.0, constrained_timeranges=False): """ Parallel media playback, flipping between the two sources. The fast version makes sure the textures continue to be updated even though they are not displayed. On the other hand, the slow version will update the textures only when needed to be displayed, causing potential seek in the underlying media, and thus undesired delays. """ m1 = ngl.Media(cfg.medias[0].filename, label="media #1") m2 = ngl.Media(cfg.medias[0].filename, label="media #2") t1 = ngl.Texture2D(data_src=m1, label="texture #1") t2 = ngl.Texture2D(data_src=m2, label="texture #2") render1 = ngl.RenderTexture(t1) render2 = ngl.RenderTexture(t2) text_settings = { "box_corner": (-1, 1 - 0.2, 0), "box_height": (0, 0.2, 0), "aspect_ratio": cfg.aspect_ratio, } render1 = ngl.Group(children=(render1, ngl.Text("media #1", **text_settings))) render2 = ngl.Group(children=(render2, ngl.Text("media #2", **text_settings))) rf1 = ngl.TimeRangeFilter(render1) rf2 = ngl.TimeRangeFilter(render2) if constrained_timeranges: rf1.set_prefetch_time(segment_time / 3.0) rf2.set_prefetch_time(segment_time / 3.0) rf1.set_max_idle_time(segment_time / 2.0) rf2.set_max_idle_time(segment_time / 2.0) t = 0 rr1 = [] rr2 = [] while t < cfg.duration: rr1.append(ngl.TimeRangeModeCont(t)) rr1.append(ngl.TimeRangeModeNoop(t + segment_time)) rr2.append(ngl.TimeRangeModeNoop(t)) rr2.append(ngl.TimeRangeModeCont(t + segment_time)) t += 2 * segment_time rf1.add_ranges(*rr1) rf2.add_ranges(*rr2) g = ngl.Group() g.add_children(rf1, rf2) if fast: g.add_children(t1, t2) return g
def rtt_clear_attachment_with_timeranges(cfg): cfg.aspect_ratio = (1, 1) # Time-disabled full screen white quad render = ngl.RenderColor(COLORS.white) time_range_filter = ngl.TimeRangeFilter(render) time_range_filter.add_ranges(ngl.TimeRangeModeNoop(0)) # Intermediate no-op RTT to force the use of a different render pass internally texture = ngl.Texture2D(width=32, height=32) rtt_noop = ngl.RenderToTexture(ngl.Identity(), [texture]) # Centered rotating quad quad = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) render = ngl.RenderColor(COLORS.orange, geometry=quad) animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, -360)] render = ngl.Rotate(render, angle=ngl.AnimatedFloat(animkf)) group = ngl.Group(children=(time_range_filter, rtt_noop, render)) # Root RTT texture = ngl.Texture2D(width=512, height=512) rtt = ngl.RenderToTexture(group, [texture]) # Full screen render of the root RTT result render = ngl.RenderTexture(texture) return ngl.Group(children=(rtt, render))
def _get_rtt_scene(cfg, features='depth', texture_ds_format=None, samples=0, mipmap_filter='none', sample_depth=False): cfg.duration = 10 cfg.aspect_ratio = (1, 1) cube = _get_cube() program = ngl.Program(vertex=_RENDER_CUBE_VERT, fragment=_RENDER_CUBE_FRAG) program.update_vert_out_vars(var_normal=ngl.IOVec3()) render = ngl.Render(cube, program) render = ngl.Scale(render, (0.5, 0.5, 0.5)) for i in range(3): rot_animkf = ngl.AnimatedFloat([ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360 * (i + 1)) ]) axis = [int(i == x) for x in range(3)] render = ngl.Rotate(render, axis=axis, anim=rot_animkf) config = ngl.GraphicConfig(render, depth_test=True) camera = ngl.Camera( config, eye=(0.0, 0.0, 3.0), center=(0.0, 0.0, 0.0), up=(0.0, 1.0, 0.0), perspective=(45.0, cfg.aspect_ratio_float), clipping=(1.0, 10.0), ) size = 1024 texture_depth = None if texture_ds_format: texture_depth = ngl.Texture2D(width=size, height=size, format=texture_ds_format) texture = ngl.Texture2D( width=size, height=size, min_filter='linear', mipmap_filter=mipmap_filter, ) rtt = ngl.RenderToTexture( camera, [texture], features=features, depth_texture=texture_depth, samples=samples, clear_color=(0, 0, 0, 1), ) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) if sample_depth: program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=_RENDER_DEPTH) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(tex0=texture_depth) else: program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(tex0=texture) return ngl.Group(children=(rtt, render))
def api_media_sharing_failure(): ctx = ngl.Context() ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend) assert ret == 0 m = ngl.Media("/dev/null") scene = ngl.Group(children=(ngl.Texture2D(data_src=m), ngl.Texture2D(data_src=m))) assert _ret_to_fourcc(ctx.set_scene(scene)) == "Eusg" # Usage error
def _shape_geometry_rtt(cfg, depth=False, samples=0): w, h = 640, 480 scene = _shape_geometry(cfg, set_normals=True) if depth: scene = ngl.GraphicConfig(scene, depth_test=True) texture = ngl.Texture2D() texture.set_width(w) texture.set_height(h) rtt = ngl.RenderToTexture(scene) rtt.add_color_textures(texture) if depth: texture = ngl.Texture2D() texture.set_format('d16_unorm') texture.set_width(w) texture.set_height(h) rtt.set_depth_texture(texture) else: rtt.set_clear_color(*COLORS['cgreen']) if samples: rtt.set_samples(samples) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) render = ngl.Render(quad, program) render.update_textures(tex0=texture) return ngl.Group(children=(rtt, render))
def cube(cfg, display_depth_buffer=False): ''' Cube with a common media Texture but a different color tainting on each side. Also includes a depth map visualization. ''' cube = ngl.Group(label='cube') frag_data = cfg.get_frag('tex-tint') program = ngl.Program(fragment=frag_data) texture = ngl.Texture2D(data_src=ngl.Media(cfg.medias[0].filename)) children = [_get_cube_side(texture, program, qi[0], qi[1], qi[2], qi[3]) for qi in _get_cube_quads()] cube.add_children(*children) for i in range(3): rot_animkf = ngl.AnimatedFloat([ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360 * (i + 1))]) axis = [int(i == x) for x in range(3)] cube = ngl.Rotate(cube, axis=axis, anim=rot_animkf) config = ngl.GraphicConfig(cube, depth_test=True) camera = ngl.Camera(config) camera.set_eye(0.0, 0.0, 2.0) camera.set_center(0.0, 0.0, 0.0) camera.set_up(0.0, 1.0, 0.0) camera.set_perspective(45.0, cfg.aspect_ratio_float) camera.set_clipping(1.0, 10.0) if not display_depth_buffer: return camera else: group = ngl.Group() depth_texture = ngl.Texture2D() depth_texture.set_format('d16_unorm') depth_texture.set_width(640) depth_texture.set_height(480) texture = ngl.Texture2D() texture.set_width(640) texture.set_height(480) rtt = ngl.RenderToTexture(camera) rtt.add_color_textures(texture) rtt.set_depth_texture(depth_texture) quad = ngl.Quad((-1.0, -1.0, 0), (1, 0, 0), (0, 1, 0)) program = ngl.Program() render = ngl.Render(quad, program) render.update_textures(tex0=texture) group.add_children(rtt, render) quad = ngl.Quad((0.0, 0.0, 0), (1, 0, 0), (0, 1, 0)) program = ngl.Program() render = ngl.Render(quad, program) render.update_textures(tex0=depth_texture) group.add_children(rtt, render) return group
def simple_transition(cfg, transition_start=2, transition_duration=4): """Fading transition between two medias""" cfg.duration = transition_start * 2 + transition_duration vertex = cfg.get_vert("dual-tex") fragment = cfg.get_frag("tex-mix") q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p1_2 = ngl.Program(vertex=vertex, fragment=fragment) p1_2.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_tex1_coord=ngl.IOVec2()) m1 = ngl.Media(cfg.medias[0].filename, label="media #1") m2 = ngl.Media(cfg.medias[1 % len(cfg.medias)].filename, label="media #2") animkf_m2 = [ ngl.AnimKeyFrameFloat(transition_start, 0), ngl.AnimKeyFrameFloat(transition_start + cfg.duration, cfg.duration), ] m2.set_time_anim(ngl.AnimatedTime(animkf_m2)) t1 = ngl.Texture2D(data_src=m1, label="texture #1") t2 = ngl.Texture2D(data_src=m2, label="texture #2") render1 = ngl.RenderTexture(t1, label="render #1") render2 = ngl.RenderTexture(t2, label="render #2") delta_animkf = [ ngl.AnimKeyFrameFloat(transition_start, 1.0), ngl.AnimKeyFrameFloat(transition_start + transition_duration, 0.0), ] delta = ngl.AnimatedFloat(delta_animkf) render1_2 = ngl.Render(q, p1_2, label="transition") render1_2.update_frag_resources(tex0=t1, tex1=t2) render1_2.update_frag_resources(delta=delta) rr1 = [] rr2 = [] rr1_2 = [] rr1.append(ngl.TimeRangeModeNoop(transition_start)) rr2.append(ngl.TimeRangeModeNoop(0)) rr2.append(ngl.TimeRangeModeCont(transition_start + transition_duration)) rr1_2.append(ngl.TimeRangeModeNoop(0)) rr1_2.append(ngl.TimeRangeModeCont(transition_start)) rr1_2.append(ngl.TimeRangeModeNoop(transition_start + transition_duration)) rf1 = ngl.TimeRangeFilter(render1, ranges=rr1) rf2 = ngl.TimeRangeFilter(render2, ranges=rr2) rf1_2 = ngl.TimeRangeFilter(render1_2, ranges=rr1_2) g = ngl.Group() g.add_children(rf1, rf1_2, rf2) return g
def simple_transition(cfg, transition_start=2, transition_duration=4): '''Fading transition between two medias''' cfg.duration = transition_start * 2 + transition_duration vertex = cfg.get_vert('dual-tex') fragment = cfg.get_frag('tex-mix') q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p1_2 = ngl.Program(vertex=vertex, fragment=fragment) m1 = ngl.Media(cfg.medias[0].filename, label='media #1') m2 = ngl.Media(cfg.medias[1 % len(cfg.medias)].filename, label='media #2') animkf_m2 = [ngl.AnimKeyFrameFloat(transition_start, 0)] m2.set_time_anim(ngl.AnimatedTime(animkf_m2)) t1 = ngl.Texture2D(data_src=m1, label='texture #1') t2 = ngl.Texture2D(data_src=m2, label='texture #2') program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) render1 = ngl.Render(q, program, label='render #1') render1.update_textures(tex0=t1) render2 = ngl.Render(q, program, label='render #2') render2.update_textures(tex0=t2) delta_animkf = [ ngl.AnimKeyFrameFloat(transition_start, 1.0), ngl.AnimKeyFrameFloat(transition_start + transition_duration, 0.0) ] delta = anim = ngl.AnimatedFloat(delta_animkf) render1_2 = ngl.Render(q, p1_2, label='transition') render1_2.update_textures(tex0=t1, tex1=t2) render1_2.update_uniforms(delta=delta) rr1 = [] rr2 = [] rr1_2 = [] rr1.append(ngl.TimeRangeModeNoop(transition_start)) rr2.append(ngl.TimeRangeModeNoop(0)) rr2.append(ngl.TimeRangeModeCont(transition_start + transition_duration)) rr1_2.append(ngl.TimeRangeModeNoop(0)) rr1_2.append(ngl.TimeRangeModeCont(transition_start)) rr1_2.append(ngl.TimeRangeModeNoop(transition_start + transition_duration)) rf1 = ngl.TimeRangeFilter(render1, ranges=rr1) rf2 = ngl.TimeRangeFilter(render2, ranges=rr2) rf1_2 = ngl.TimeRangeFilter(render1_2, ranges=rr1_2) g = ngl.Group() g.add_children(rf1, rf1_2, rf2) return g
def _get_scene( self, file0, file1, diff_mode=False, split=(0.5, 0.5), vertical_split=True, show_r=True, show_g=True, show_b=True, show_a=True, premultiplied=False, threshold=0.001, ): vert = pkgutil.get_data("pynodegl_utils.diff.shaders", "diff.vert") frag = pkgutil.get_data("pynodegl_utils.diff.shaders", "diff.frag") assert vert is not None and frag is not None quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) prog = ngl.Program(vertex=vert.decode(), fragment=frag.decode()) prog.update_vert_out_vars( uv=ngl.IOVec2(), tex0_coord=ngl.IOVec2(), tex1_coord=ngl.IOVec2(), ) scene = ngl.Render(quad, prog) scene.update_frag_resources( tex0=ngl.Texture2D(data_src=ngl.Media(file0)), tex1=ngl.Texture2D(data_src=ngl.Media(file1)), split=ngl.UniformVec2(split, live_id="split"), diff_mode=ngl.UniformBool(diff_mode, live_id="diff_mode"), vertical_split=ngl.UniformBool(vertical_split, live_id="vertical_split"), show_r=ngl.UniformBool(show_r, live_id="show_r"), show_g=ngl.UniformBool(show_g, live_id="show_g"), show_b=ngl.UniformBool(show_b, live_id="show_b"), show_a=ngl.UniformBool(show_a, live_id="show_a"), premultiplied=ngl.UniformBool(premultiplied, live_id="premultiplied"), threshold=ngl.UniformFloat(threshold, live_id="threshold", live_max=0.1), ) scene.update_vert_resources( reframing_scale=ngl.UniformFloat( self._reframing_scale, live_id="reframing_scale", live_min=self._MIN_SCALE, live_max=self._MAX_SCALE, ), reframing_off=ngl.UniformVec2( self._reframing_off, live_id="reframing_off", live_min=(-self._MAX_SCALE, -self._MAX_SCALE), live_max=(self._MAX_SCALE, self._MAX_SCALE), ), ) return scene
def histogram(cfg): """Histogram using compute shaders""" m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) g = ngl.Group() m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) h = ngl.Block(label="histogram_block", layout="std430") h.add_fields( ngl.BufferUInt(256, label="r"), ngl.BufferUInt(256, label="g"), ngl.BufferUInt(256, label="b"), ngl.UniformUInt(label="maximum"), ) r = ngl.RenderTexture(t) proxy_size = 128 proxy = ngl.Texture2D(width=proxy_size, height=proxy_size) rtt = ngl.RenderToTexture(r) rtt.add_color_textures(proxy) g.add_children(rtt) compute_program = ngl.ComputeProgram(cfg.get_comp("histogram-clear"), workgroup_size=(1, 1, 1)) compute_program.update_properties(hist=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroup_count=(256, 1, 1), program=compute_program, label="histogram-clear") compute.update_resources(hist=h) g.add_children(compute) local_size = 8 group_size = proxy_size / local_size compute_program = ngl.ComputeProgram(cfg.get_comp("histogram-exec"), workgroup_size=(local_size, local_size, 1)) compute = ngl.Compute(workgroup_count=(group_size, group_size, 1), program=compute_program, label="histogram-exec") compute.update_resources(hist=h, source=proxy) compute_program.update_properties(hist=ngl.ResourceProps(writable=True)) compute_program.update_properties(source=ngl.ResourceProps(as_image=True)) g.add_children(compute) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p = ngl.Program(vertex=cfg.get_vert("histogram-display"), fragment=cfg.get_frag("histogram-display")) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=t, hist=h) g.add_children(render) return g
def histogram(cfg): '''Histogram using compute shaders''' m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) g = ngl.Group() m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) h = ngl.Block(label='histogram_block', layout='std430') h.add_fields( ngl.BufferUInt(256, label='r'), ngl.BufferUInt(256, label='g'), ngl.BufferUInt(256, label='b'), ngl.UniformInt(label='maximum'), ) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) r = ngl.Render(q) r.update_textures(tex0=t) proxy_size = 128 proxy = ngl.Texture2D(width=proxy_size, height=proxy_size) rtt = ngl.RenderToTexture(r) rtt.add_color_textures(proxy) g.add_children(rtt) shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_header = '#version %s\n' % shader_version if cfg.backend == 'gles' and cfg.system == 'Android': shader_header += '#extension GL_ANDROID_extension_pack_es31a: require\n' compute_program = ngl.ComputeProgram(shader_header + cfg.get_comp('histogram-clear')) compute = ngl.Compute(256, 1, 1, compute_program, label='histogram-clear') compute.update_blocks(histogram_buffer=h) g.add_children(compute) local_size = 8 group_size = proxy_size / local_size compute_shader = cfg.get_comp('histogram-exec') % {'local_size': local_size} compute_program = ngl.ComputeProgram(shader_header + compute_shader) compute = ngl.Compute(group_size, group_size, 1, compute_program, label='histogram-exec') compute.update_blocks(histogram_buffer=h) compute.update_textures(source=proxy) g.add_children(compute) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p = ngl.Program(vertex=shader_header + cfg.get_vert('histogram-display'), fragment=shader_header + cfg.get_frag('histogram-display')) render = ngl.Render(q, p) render.update_textures(tex0=t) render.update_blocks(histogram_buffer=h) g.add_children(render) return g
def _rtt_load_attachment(): background = ngl.RenderColor(COLORS.white) render = ngl.RenderColor(COLORS.orange) texture = ngl.Texture2D(width=16, height=16) rtt = ngl.RenderToTexture(render, [texture]) texture_noop = ngl.Texture2D(width=16, height=16) rtt_noop = ngl.RenderToTexture(render, [texture_noop]) quad = ngl.Quad((0, 0, 0), (1, 0, 0), (0, 1, 0)) foreground = ngl.RenderTexture(texture, geometry=quad) return ngl.Group(children=(background, rtt, rtt_noop, foreground))
def media_timeranges_rtt(cfg): m0 = cfg.medias[0] cfg.duration = d = 10 cfg.aspect_ratio = (m0.width, m0.height) # Use a media/texture as leaf to exercise its prefetch/release mechanism media = ngl.Media(m0.filename) texture = ngl.Texture2D(data_src=media) # Diamond tree on the same media texture render0 = ngl.RenderTexture(texture, label="leaf 0") render1 = ngl.RenderTexture(texture, label="leaf 1") # Create intermediate RTT "proxy" to exercise prefetch/release at this # level as well dst_tex0 = ngl.Texture2D(width=m0.width, height=m0.height) dst_tex1 = ngl.Texture2D(width=m0.width, height=m0.height) rtt0 = ngl.RenderToTexture(render0, [dst_tex0]) rtt1 = ngl.RenderToTexture(render1, [dst_tex1]) # Render the 2 RTTs vertically split (one half content each) quad0 = ngl.Quad((-1, -1, 0), (1, 0, 0), (0, 2, 0), uv_corner=(0, 0), uv_width=(0.5, 0)) quad1 = ngl.Quad((0, -1, 0), (1, 0, 0), (0, 2, 0), uv_corner=(0.5, 0), uv_width=(0.5, 0)) rtt_render0 = ngl.RenderTexture(dst_tex0, geometry=quad0, label="render RTT 0") rtt_render1 = ngl.RenderTexture(dst_tex1, geometry=quad1, label="render RTT 1") proxy0 = ngl.Group(children=(rtt0, rtt_render0), label="proxy 0") proxy1 = ngl.Group(children=(rtt1, rtt_render1), label="proxy 1") # We want to make sure the idle times are enough to exercise the # prefetch/release mechanism prefetch_time = 1 assert prefetch_time < d / 5 # Split the presentation in 5 segments such that there are inactive times, # prefetch times and both overlapping and non-overlapping times for the # RTTs ranges0 = ( ngl.TimeRangeModeNoop(0), ngl.TimeRangeModeCont(1 / 5 * d), ngl.TimeRangeModeNoop(3 / 5 * d), ) ranges1 = ( ngl.TimeRangeModeNoop(0), ngl.TimeRangeModeCont(2 / 5 * d), ngl.TimeRangeModeNoop(4 / 5 * d), ) trange0 = ngl.TimeRangeFilter(proxy0, ranges=ranges0, prefetch_time=prefetch_time, label="left") trange1 = ngl.TimeRangeFilter(proxy1, ranges=ranges1, prefetch_time=prefetch_time, label="right") return ngl.Group(children=(trange0, trange1))
def rtt_clear_attachment_with_timeranges(cfg): cfg.aspect_ratio = (1, 1) # Time-disabled full screen white quad quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['white'])) time_range_filter = ngl.TimeRangeFilter(render) time_range_filter.add_ranges(ngl.TimeRangeModeNoop(0)) # Intermediate no-op RTT to force the use of a different render pass internally texture = ngl.Texture2D(width=32, height=32) rtt_noop = ngl.RenderToTexture(ngl.Identity(), [texture]) # Centered rotating quad quad = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['orange'])) animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, -360) ] render = ngl.Rotate(render, anim=ngl.AnimatedFloat(animkf)) group = ngl.Group(children=(time_range_filter, rtt_noop, render)) # Root RTT texture = ngl.Texture2D(width=512, height=512) rtt = ngl.RenderToTexture(group, [texture]) # Full screen render of the root RTT result quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(tex0=texture) return ngl.Group(children=(rtt, render))
def centered_media(cfg, uv_corner_x=0, uv_corner_y=0, uv_width=1, uv_height=1, progress_bar=True): '''A simple centered media with an optional progress bar in the shader''' m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0), (uv_corner_x, uv_corner_y), (uv_width, 0), (0, uv_height)) m = ngl.Media(m0.filename) t = ngl.Texture2D(data_src=m) p = ngl.Program() render = ngl.Render(q, p) render.update_textures(tex0=t) if progress_bar: p.set_fragment(cfg.get_frag('progress-bar')) media_duration = ngl.UniformFloat(m0.duration) ar = ngl.UniformFloat(cfg.aspect_ratio_float) render.update_uniforms(media_duration=media_duration, ar=ar) return render
def animated_uniform(cfg): '''Uniform mat4 animated with a transform chain''' m0 = cfg.medias[0] cfg.aspect_ratio = (m0.width, m0.height) q = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) m = ngl.Media(m0.filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('matrix-transform')) ts = ngl.Render(q, p) ts.update_textures(tex0=t) scale_animkf = [ ngl.AnimKeyFrameVec3(0, (1, 1, 1)), ngl.AnimKeyFrameVec3(cfg.duration, (0.1, 0.1, 0.1), 'quartic_out') ] s = ngl.Scale(ngl.Identity(), anim=ngl.AnimatedVec3(scale_animkf)) rotate_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360, 'exp_out') ] r = ngl.Rotate(s, axis=(0, 0, 1), anim=ngl.AnimatedFloat(rotate_animkf)) u = ngl.UniformMat4(transform=r) ts.update_uniforms(matrix=u) return ts
def texture_mipmap(cfg, show_dbg_points=False): cfg.aspect_ratio = (1, 1) cuepoints = _get_texture_mipmap_cuepoints() black = (0, 0, 0, 255) white = (255, 255, 255, 255) p = _N // 2 cb_data = array.array( 'B', ((black + white) * p + (white + black) * p) * p, ) cb_buffer = ngl.BufferUBVec4(data=cb_data) texture = ngl.Texture2D( width=_N, height=_N, min_filter='nearest', mipmap_filter='linear', data_src=cb_buffer, ) program = ngl.Program(vertex=_RENDER_TEXTURE_LOD_VERT, fragment=_RENDER_TEXTURE_LOD_FRAG) program.update_vert_out_vars(var_uvcoord=ngl.IOVec2()) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) render = ngl.Render(quad, program) render.update_frag_resources(tex0=texture) group = ngl.Group(children=(render, )) if show_dbg_points: group.add_children(get_debug_points(cfg, cuepoints)) return group
def animated_uniform(cfg): """Uniform mat4 animated with a transform chain""" m0 = cfg.medias[0] cfg.aspect_ratio = (m0.width, m0.height) q = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) m = ngl.Media(m0.filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert("texture"), fragment=cfg.get_frag("matrix-transform")) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) ts = ngl.Render(q, p) ts.update_frag_resources(tex0=t) scale_animkf = [ ngl.AnimKeyFrameVec3(0, (1, 1, 1)), ngl.AnimKeyFrameVec3(cfg.duration, (0.1, 0.1, 0.1), "quartic_out"), ] s = ngl.Scale(ngl.Identity(), factors=ngl.AnimatedVec3(scale_animkf)) rotate_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360, "exp_out") ] r = ngl.Rotate(s, axis=(0, 0, 1), angle=ngl.AnimatedFloat(rotate_animkf)) u = ngl.UniformMat4(transform=r) ts.update_frag_resources(matrix=u) return ts
def centered_media(cfg, uv_corner=(0, 0), uv_width=(1, 0), uv_height=(0, 1), progress_bar=True): '''A simple centered media with an optional progress bar in the shader''' m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0), uv_corner, uv_width, uv_height) m = ngl.Media(m0.filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) p.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=t) if progress_bar: p.set_fragment(cfg.get_frag('progress-bar')) media_duration = ngl.UniformFloat(m0.duration) ar = ngl.UniformFloat(cfg.aspect_ratio_float) render.update_frag_resources(media_duration=media_duration, ar=ar) return render
def lut3d(cfg, xsplit=.3, trilinear=True): '''Lookup Table 3D using a Texture3D''' level = 6 level2 = level**2 # Generated with `ffmpeg -f lavfi -i haldclutsrc=6,curves=vintage -f # rawvideo -frames:v 1 lut3d.raw` lut3d_filename = op.join(op.dirname(__file__), 'data', 'lut3d.raw') cfg.files.append(lut3d_filename) lut3d_buf = ngl.BufferUBVec3(filename=lut3d_filename) lut3d_tex = ngl.Texture3D(data_src=lut3d_buf, width=level2, height=level2, depth=level2) if trilinear: lut3d_tex.set_min_filter('linear') lut3d_tex.set_mag_filter('linear') m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) video = ngl.Media(m0.filename) video_tex = ngl.Texture2D(data_src=video) shader_version = '300 es' if cfg.backend == 'gles' else '330' shader_header = '#version %s\n' % shader_version prog = ngl.Program(fragment=shader_header + cfg.get_frag('lut3d'), vertex=shader_header + cfg.get_vert('lut3d')) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) render = ngl.Render(quad, prog) render.update_textures(tex0=video_tex) render.update_textures(lut3d=lut3d_tex) render.update_uniforms(xsplit=ngl.UniformFloat(value=xsplit)) return render
def lut3d(cfg, xsplit=.3, trilinear=True): '''Lookup Table 3D using a Texture3D''' level = 6 level2 = level**2 # Generated with `ffmpeg -f lavfi -i haldclutsrc=6,curves=vintage,format=rgba # -f rawvideo -frames:v 1 lut3d.raw` lut3d_filename = op.join(op.dirname(__file__), 'data', 'lut3d.raw') cfg.files.append(lut3d_filename) lut3d_buf = ngl.BufferUBVec4(filename=lut3d_filename) lut3d_tex = ngl.Texture3D(data_src=lut3d_buf, width=level2, height=level2, depth=level2) if trilinear: lut3d_tex.set_min_filter('linear') lut3d_tex.set_mag_filter('linear') m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) video = ngl.Media(m0.filename) video_tex = ngl.Texture2D(data_src=video) prog = ngl.Program(fragment=cfg.get_frag('lut3d'), vertex=cfg.get_vert('lut3d')) prog.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) render = ngl.Render(quad, prog) render.update_frag_resources(tex0=video_tex, lut3d=lut3d_tex) render.update_frag_resources(xsplit=ngl.UniformFloat(value=xsplit)) return render
def queued_medias(cfg, overlap_time=1.0, dim=3): """Queue of medias, mainly used as a demonstration for the prefetch/release mechanism""" nb_videos = dim * dim tqs = [] ag = AutoGrid(range(nb_videos)) for video_id, _, col, pos in ag: start = video_id * cfg.duration / nb_videos animkf = [ ngl.AnimKeyFrameFloat(start, 0), ngl.AnimKeyFrameFloat(start + cfg.duration, cfg.duration), ] m = ngl.Media(cfg.medias[video_id % len(cfg.medias)].filename, time_anim=ngl.AnimatedTime(animkf)) m.set_label("media #%d" % video_id) t = ngl.Texture2D(data_src=m) render = ngl.RenderTexture(t) render.set_label("render #%d" % video_id) render = ag.place_node(render, (col, pos)) rf = ngl.TimeRangeFilter(render) if start: rf.add_ranges(ngl.TimeRangeModeNoop(0)) rf.add_ranges( ngl.TimeRangeModeCont(start), ngl.TimeRangeModeNoop(start + cfg.duration / nb_videos + overlap_time)) tqs.append(rf) return ngl.Group(children=tqs)
def media_exposed_time(cfg): m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) vert = textwrap.dedent( """\ void main() { ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * vec4(ngl_position, 1.0); uv = ngl_uvcoord; } """ ) frag = textwrap.dedent( """\ void main() { ngl_out_color = vec4(vec3(step(0.0, tex0_ts/duration - uv.x)), 1.0); } """ ) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) media = ngl.Media(m0.filename) texture = ngl.Texture2D(data_src=media) program = ngl.Program(vertex=vert, fragment=frag) program.update_vert_out_vars(uv=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(tex0=texture, duration=ngl.UniformFloat(cfg.duration)) return render
def quaternion(cfg): """Animated quaternion used to rotate a plane""" cfg.duration = 10.0 step = cfg.duration / 5.0 x = math.sqrt(0.5) quat_animkf = [ ngl.AnimKeyFrameQuat(0 * step, (0, 0, 0, 1)), ngl.AnimKeyFrameQuat(1 * step, (0, 0, -x, x)), ngl.AnimKeyFrameQuat(2 * step, (0, 1, 0, 0)), ngl.AnimKeyFrameQuat(3 * step, (1, 0, 0, 0)), ngl.AnimKeyFrameQuat(4 * step, (x, 0, 0, x)), ngl.AnimKeyFrameQuat(5 * step, (0, 0, 0, 1)), ] quat = ngl.AnimatedQuat(quat_animkf, as_mat4=True) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert("uniform-mat4"), fragment=cfg.get_frag("texture")) p.update_vert_out_vars(var_normal=ngl.IOVec3(), var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=t) render.update_vert_resources(transformation_matrix=quat) camera = ngl.Camera(render) camera.set_eye(0.0, 0.0, 4.0) camera.set_center(0.0, 0.0, 0.0) camera.set_up(0.0, 1.0, 0.0) camera.set_perspective(45.0, cfg.aspect_ratio_float) camera.set_clipping(1.0, 10.0) return camera
def quaternion(cfg): '''Animated quaternion used to rotate a plane''' cfg.duration = 10. step = cfg.duration / 5. x = math.sqrt(0.5) quat_animkf = [ ngl.AnimKeyFrameQuat(0 * step, (0, 0, 0, 1)), ngl.AnimKeyFrameQuat(1 * step, (0, 0,-x, x)), ngl.AnimKeyFrameQuat(2 * step, (0, 1, 0, 0)), ngl.AnimKeyFrameQuat(3 * step, (1, 0, 0, 0)), ngl.AnimKeyFrameQuat(4 * step, (x, 0, 0, x)), ngl.AnimKeyFrameQuat(5 * step, (0, 0, 0, 1)), ] quat = ngl.AnimatedQuat(quat_animkf, as_mat4=True) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) p = ngl.Program(vertex=cfg.get_vert('uniform-mat4')) render = ngl.Render(q, p) render.update_textures(tex0=t) render.update_uniforms(transformation_matrix=quat) camera = ngl.Camera(render) camera.set_eye(0.0, 0.0, 4.0) camera.set_center(0.0, 0.0, 0.0) camera.set_up(0.0, 1.0, 0.0) camera.set_perspective(45.0, cfg.aspect_ratio_float) camera.set_clipping(1.0, 10.0) return camera
def buffer_dove(cfg, bgcolor1=(0.6, 0, 0), bgcolor2=(0.8, 0.8, 0), bilinear_filtering=True): """Blending of a Render using a Buffer as data source""" cfg.duration = 3.0 # Credits: https://icons8.com/icon/40514/dove # (Raw data is the premultiplied) icon_filename = op.join(op.dirname(__file__), "data", "icons8-dove.raw") cfg.files.append(icon_filename) w, h = (96, 96) cfg.aspect_ratio = (w, h) img_buf = ngl.BufferUBVec4(filename=icon_filename, label="icon raw buffer") img_tex = ngl.Texture2D(data_src=img_buf, width=w, height=h) if bilinear_filtering: img_tex.set_mag_filter("linear") quad = ngl.Quad((-0.5, -0.5, 0.1), (1, 0, 0), (0, 1, 0)) render = ngl.RenderTexture(img_tex, geometry=quad, blending="src_over") shape_bg = ngl.Circle(radius=0.6, npoints=256) color_animkf = [ ngl.AnimKeyFrameColor(0, bgcolor1), ngl.AnimKeyFrameColor(cfg.duration / 2.0, bgcolor2), ngl.AnimKeyFrameColor(cfg.duration, bgcolor1), ] ucolor = ngl.AnimatedColor(color_animkf) render_bg = ngl.RenderColor(ucolor, geometry=shape_bg, label="background") return ngl.Group(children=(render_bg, render))
def queued_medias(cfg, overlap_time=1., dim=3): '''Queue of medias, mainly used as a demonstration for the prefetch/release mechanism''' qw = qh = 2. / dim nb_videos = dim * dim tqs = [] p = ngl.Program() for y in range(dim): for x in range(dim): video_id = y * dim + x start = video_id * cfg.duration / nb_videos animkf = [ngl.AnimKeyFrameFloat(start, 0)] m = ngl.Media(cfg.medias[video_id % len(cfg.medias)].filename, time_anim=ngl.AnimatedTime(animkf)) m.set_label('media #%d' % video_id) corner = (-1. + x * qw, 1. - (y + 1) * qh, 0) q = ngl.Quad(corner, (qw, 0, 0), (0, qh, 0)) t = ngl.Texture2D(data_src=m) render = ngl.Render(q, p) render.set_label('render #%d' % video_id) render.update_textures(tex0=t) rf = ngl.TimeRangeFilter(render) if start: rf.add_ranges(ngl.TimeRangeModeNoop(0)) rf.add_ranges( ngl.TimeRangeModeCont(start), ngl.TimeRangeModeNoop(start + cfg.duration / nb_videos + overlap_time)) tqs.append(rf) return ngl.Group(children=tqs)
def queued_medias(cfg, overlap_time=1., dim=3): '''Queue of medias, mainly used as a demonstration for the prefetch/release mechanism''' nb_videos = dim * dim tqs = [] q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) ag = AutoGrid(range(nb_videos)) for video_id, _, col, pos in ag: start = video_id * cfg.duration / nb_videos animkf = [ngl.AnimKeyFrameFloat(start, 0)] m = ngl.Media(cfg.medias[video_id % len(cfg.medias)].filename, time_anim=ngl.AnimatedTime(animkf)) m.set_label('media #%d' % video_id) t = ngl.Texture2D(data_src=m) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) program.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) render = ngl.Render(q, program) render.set_label('render #%d' % video_id) render.update_frag_resources(tex0=t) render = ag.place_node(render, (col, pos)) rf = ngl.TimeRangeFilter(render) if start: rf.add_ranges(ngl.TimeRangeModeNoop(0)) rf.add_ranges(ngl.TimeRangeModeCont(start), ngl.TimeRangeModeNoop(start + cfg.duration/nb_videos + overlap_time)) tqs.append(rf) return ngl.Group(children=tqs)
def _get_time_scene(cfg): m0 = cfg.medias[0] media_seek = 10 noop_duration = 2 prefetch_duration = 2 freeze_duration = 3 playback_duration = 5 range_start = noop_duration + prefetch_duration play_start = range_start + freeze_duration play_stop = play_start + playback_duration range_stop = play_stop + freeze_duration duration = range_stop + noop_duration cfg.duration = duration cfg.aspect_ratio = (m0.width, m0.height) media_animkf = [ ngl.AnimKeyFrameFloat(play_start, media_seek), ngl.AnimKeyFrameFloat(play_stop, media_seek + playback_duration), ] m = ngl.Media(m0.filename, time_anim=ngl.AnimatedTime(media_animkf)) t = ngl.Texture2D(data_src=m) r = ngl.RenderTexture(t) time_ranges = [ ngl.TimeRangeModeNoop(0), ngl.TimeRangeModeCont(range_start), ngl.TimeRangeModeNoop(range_stop), ] rf = ngl.TimeRangeFilter(r, ranges=time_ranges, prefetch_time=prefetch_duration) return rf