コード例 #1
0
ファイル: rtt.py プロジェクト: iCodeIN/gopro-lib-node.gl
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))
コード例 #2
0
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
コード例 #3
0
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))
コード例 #4
0
ファイル: rtt.py プロジェクト: iCodeIN/gopro-lib-node.gl
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))
コード例 #5
0
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
コード例 #6
0
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))
コード例 #7
0
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
コード例 #8
0
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
コード例 #9
0
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
コード例 #10
0
 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
コード例 #11
0
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
コード例 #12
0
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
コード例 #13
0
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))
コード例 #14
0
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))
コード例 #15
0
ファイル: rtt.py プロジェクト: mbouron/gopro-lib-node.gl
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))
コード例 #16
0
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
コード例 #17
0
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
コード例 #18
0
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
コード例 #19
0
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
コード例 #20
0
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
コード例 #21
0
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
コード例 #22
0
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
コード例 #23
0
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)
コード例 #24
0
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
コード例 #25
0
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
コード例 #26
0
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
コード例 #27
0
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))
コード例 #28
0
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)
コード例 #29
0
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)
コード例 #30
0
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