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 _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 _get_texture_cubemap_from_mrt_scene_2_pass(samples=0): group = ngl.Group() quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) cube = ngl.TextureCube(size=64, min_filter="linear", mag_filter="linear") layer_base = 0 for layer_count, fragment in ((2, _RENDER_TO_CUBEMAP_1_FRAG), (4, _RENDER_TO_CUBEMAP_2_FRAG)): program = ngl.Program(vertex=_RENDER_TO_CUBEMAP_VERT, fragment=fragment, nb_frag_output=layer_count) program.update_vert_out_vars(var_uvcoord=ngl.IOVec3()) render = ngl.Render(quad, program) color_textures = [ ngl.TextureView(cube, layer) for layer in range(layer_base, layer_base + layer_count) ] rtt = ngl.RenderToTexture(render, color_textures, samples=samples) group.add_children(rtt) layer_base += layer_count program = ngl.Program(vertex=_RENDER_CUBEMAP_VERT, fragment=_RENDER_CUBEMAP_FRAG) program.update_vert_out_vars(var_uvcoord=ngl.IOVec3()) render = ngl.Render(quad, program) render.update_frag_resources(tex0=cube) group.add_children(render) return group
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) 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 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 _get_compositing_scene(cfg, op, show_label=False): cfg.aspect_ratio = (1, 1) cfg.duration = 6 # We can not use a circle geometry because the whole areas must be # rasterized for the compositing to work, so instead we build 2 overlapping # quad into which we draw colored circles, offsetted with an animation. # Alternatively, we could use a RTT. quad = ngl.Quad(corner=(-1, -1, 0), width=(2, 0, 0), height=(0, 2, 0)) prog = ngl.Program(vertex=_VERTEX, fragment=_FRAGMENT) prog.update_vert_out_vars(uv=ngl.IOVec2()) A_off_kf = ( ngl.AnimKeyFrameVec2(0, (-1 / 3, 0)), ngl.AnimKeyFrameVec2(cfg.duration / 2, (1 / 3, 0)), ngl.AnimKeyFrameVec2(cfg.duration, (-1 / 3, 0)), ) B_off_kf = ( ngl.AnimKeyFrameVec2(0, (1 / 3, 0)), ngl.AnimKeyFrameVec2(cfg.duration / 2, (-1 / 3, 0)), ngl.AnimKeyFrameVec2(cfg.duration, (1 / 3, 0)), ) A_off = ngl.AnimatedVec2(A_off_kf) B_off = ngl.AnimatedVec2(B_off_kf) A = ngl.Render(quad, prog, label="A") A.update_frag_resources(color=ngl.UniformVec3(value=COLORS.azure), off=A_off) B = ngl.Render(quad, prog, label="B", blending=op) B.update_frag_resources(color=ngl.UniformVec3(value=COLORS.orange), off=B_off) bg = ngl.RenderColor(blending="dst_over") # draw A in current FBO, then draw B with the current operator, and # then result goes over the white background ret = ngl.Group(children=(A, B, bg)) if show_label: label_h = 1 / 4 label_pad = 0.1 label = ngl.Text( op, fg_color=COLORS.black, bg_color=(0.8, 0.8, 0.8), bg_opacity=1, box_corner=(label_pad / 2 - 1, 1 - label_h - label_pad / 2, 0), box_width=(2 - label_pad, 0, 0), box_height=(0, label_h, 0), ) ret.add_children(label) return ret
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'), ) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) r = ngl.Render(q, p) r.update_frag_resources(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) 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 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 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 _get_live_shared_uniform_with_block_scene(cfg, color, layout, debug_positions): vertex = ''' void main() { ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * ngl_position; } ''' fragment = ''' void main() { ngl_out_color = data.color; } ''' program = ngl.Program(vertex=vertex, fragment=fragment) group = ngl.Group() for i in range(2): block = ngl.Block(fields=[color], layout=layout) quad = ngl.Quad((-1 + i, -1 + i, 0), (1, 0, 0), (0, 1, 0)) render = ngl.Render(quad, program) render.update_frag_resources(data=block) group.add_children(render) if debug_positions: group.add_children(get_debug_points(cfg, _SHARED_UNIFORM_CUEPOINTS)) return group
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 velocity_circle_distort_2d(cfg): cfg.duration = 4.0 cfg.aspect_ratio = (1, 1) coords = list(equilateral_triangle_coords()) coords.append(coords[0]) pos_kf = [ ngl.AnimKeyFrameVec2(cfg.duration * i / 3.0, pos[0:2], "exp_in_out") for i, pos in enumerate(coords) ] anim = ngl.AnimatedVec2(pos_kf) velocity = ngl.VelocityVec2(anim) vert = textwrap.dedent("""\ void main() { float distort_max = 0.1; float velocity_l = length(velocity); float direction_l = length(ngl_position); vec2 normed_velocity = velocity_l == 0.0 ? vec2(0.0) : -velocity / velocity_l; vec2 normed_direction = direction_l == 0.0 ? vec2(0.0) : ngl_position.xy / direction_l; float distort = clamp(dot(normed_velocity, normed_direction) / 2.0 * distort_max, 0.0, 1.0); vec4 pos = vec4(ngl_position, 1.0) + vec4(translate, 0.0, 0.0) + vec4(-distort * velocity, 0.0, 0.0); ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * pos; } """) geom = ngl.Circle(radius=0.2, npoints=128) prog = ngl.Program(vertex=vert, fragment=cfg.get_frag("color")) shape = ngl.Render(geom, prog) shape.update_frag_resources(color=ngl.UniformVec3(COLORS.white), opacity=ngl.UniformFloat(1)) shape.update_vert_resources(velocity=velocity, translate=anim) return shape
def velocity_triangle_rotate(cfg): cfg.duration = 5.0 cfg.aspect_ratio = (1, 1) anim_kf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360 * 3, "circular_in_out"), ] anim = ngl.AnimatedFloat(anim_kf) velocity = ngl.VelocityFloat(anim) frag = textwrap.dedent("""\ void main() { float v = clamp(velocity / 3000., 0.0, 1.0); ngl_out_color = vec4(v, v / 2.0, 0.0, 1.0); } """) p0, p1, p2 = equilateral_triangle_coords(2.0) triangle = ngl.RenderColor(COLORS.white, geometry=ngl.Triangle(p0, p1, p2)) triangle = ngl.Rotate(triangle, angle=anim) prog_c = ngl.Program(vertex=cfg.get_vert("color"), fragment=frag) circle = ngl.Render(ngl.Circle(radius=1.0, npoints=128), prog_c) circle.update_frag_resources(velocity=velocity) return ngl.Group(children=(circle, triangle))
def triangle(cfg, size=0.5): '''Rotating triangle with edge coloring specified in a vertex attribute''' b = size * math.sqrt(3) / 2.0 c = size * 1 / 2. cfg.duration = 3. cfg.aspect_ratio = (1, 1) colors_data = array.array( 'f', [0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0]) colors_buffer = ngl.BufferVec4(data=colors_data) triangle = ngl.Triangle((-b, -c, 0), (b, -c, 0), (0, size, 0)) p = ngl.Program(fragment=cfg.get_frag('color'), vertex=cfg.get_vert('triangle')) p.update_vert_out_vars(color=ngl.IOVec4()) node = ngl.Render(triangle, p) node.update_attributes(edge_color=colors_buffer) animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration / 3., -360 / 3., 'exp_in_out'), ngl.AnimKeyFrameFloat(2 * cfg.duration / 3., -2 * 360 / 3., 'exp_in_out'), ngl.AnimKeyFrameFloat(cfg.duration, -360, 'exp_in_out') ] node = ngl.Rotate(node, anim=ngl.AnimatedFloat(animkf)) return node
def square2circle(cfg, square_color=(0.9, 0.1, 0.3, 1.0), circle_color=(1.0, 1.0, 1.0, 1.0)): '''Morphing of a square (composed of many vertices) into a circle''' cfg.duration = 5 cfg.aspect_ratio = (1, 1) def sqxf(t): # square x coordinates clockwise starting top-left if t < 1/4.: return t*4 if t < 1/2.: return 1 if t < 3/4.: return 1.-(t-.5)*4 return 0 def sqyf(t): # square y coordinates clockwise starting top-left if t < 1/4.: return 1 if t < 1/2.: return 1.-(t-.25)*4 if t < 3/4.: return 0 return (t-.75)*4 n = 1024 # number of vertices s = 1.25 # shapes scale interp = 'exp_in_out' center_vertex = [0, 0, 0] square_vertices = array.array('f', center_vertex) for i in range(n): x = (sqxf(i / float(n)) - .5) * s y = (sqyf(i / float(n)) - .5) * s square_vertices.extend([x, y, 0]) circle_vertices = array.array('f', center_vertex) step = 2 * math.pi / float(n) for i in range(n): angle = i * step - math.pi/4. x = math.sin(angle) * .5 * s y = math.cos(angle) * .5 * s circle_vertices.extend([x, y, 0]) indices = array.array('H') for i in range(1, n + 1): indices.extend([0, i, i + 1]) indices[-1] = 1 vertices_animkf = [ ngl.AnimKeyFrameBuffer(0, square_vertices), ngl.AnimKeyFrameBuffer(cfg.duration/2., circle_vertices, interp), ngl.AnimKeyFrameBuffer(cfg.duration, square_vertices, interp), ] vertices = ngl.AnimatedBufferVec3(vertices_animkf) color_animkf = [ ngl.AnimKeyFrameVec4(0, square_color), ngl.AnimKeyFrameVec4(cfg.duration/2., circle_color, interp), ngl.AnimKeyFrameVec4(cfg.duration, square_color, interp), ] ucolor = ngl.AnimatedVec4(color_animkf) geom = ngl.Geometry(vertices, indices=ngl.BufferUShort(data=indices)) p = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) render = ngl.Render(geom, p) render.update_frag_resources(color=ucolor) return render
def get_debug_points(cfg, points, radius=0.025, color=COLORS['green'], text_size=(0.1, 0.1)): prog = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) g = ngl.Group() circle = ngl.Circle(radius=radius) circle_render = ngl.Render(circle, prog) circle_render.update_uniforms(color=ngl.UniformVec4(value=color)) box_w = (text_size[0], 0, 0) box_h = (0, text_size[1], 0) for pos_name, position in points.items(): text = ngl.Text(pos_name, box_width=box_w, box_height=box_h, bg_color=(0, 0, 0, 0), valign='top') text = ngl.Translate(text, (1 + radius, 1 - radius - text_size[1], 0)) point = ngl.Group(children=(circle_render, text)) point = ngl.Translate(point, list(position) + [0]) g.add_children(point) return ngl.GraphicConfig(g, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one', label='Debug circles')
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 data_eval(cfg): cfg.aspect_ratio = (1, 1) # Entangled dependencies between evals t = ngl.Time() a = ngl.UniformFloat(0.7) b = ngl.UniformFloat(0.3) x = ngl.EvalFloat("sin(a - b + t*4)") x.update_resources(t=t, a=a, b=b) color = ngl.EvalVec4( expr0="sat(sin(x + t*4)/2 + wiggle/3)", expr1="abs(fract(sin(t + a)))", expr2=None, # re-use expr1 expr3="1", ) color.update_resources(wiggle=ngl.NoiseFloat(), t=t, a=a, x=x) vert = textwrap.dedent("""\ void main() { ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * vec4(ngl_position, 1.0); } """) frag = textwrap.dedent("""\ void main() { ngl_out_color = color; } """) program = ngl.Program(vertex=vert, fragment=frag) geometry = ngl.Quad(corner=(-1, -1, 0), width=(2, 0, 0), height=(0, 2, 0)) render = ngl.Render(geometry, program) render.update_frag_resources(color=color) return render
def data_mat_iovars(cfg): cfg.aspect_ratio = (1, 1) vert = textwrap.dedent("""\ void main() { ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * vec4(ngl_position, 1.0); var_mat3 = mat3(1.0); var_mat4 = mat4(1.0); var_vec4 = vec4(1.0, 0.5, 0.0, 1.0); } """) frag = textwrap.dedent("""\ void main() { ngl_out_color = mat4(var_mat3) * var_mat4 * var_vec4; } """) program = ngl.Program(vertex=vert, fragment=frag) program.update_vert_out_vars( var_mat3=ngl.IOMat3(), var_mat4=ngl.IOMat4(), var_vec4=ngl.IOVec4(), ) geometry = ngl.Quad(corner=(-1, -1, 0), width=(2, 0, 0), height=(0, 2, 0)) render = ngl.Render(geometry, program) return render
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 _compute_animation(cfg, animate_pre_render=True): cfg.duration = 5 cfg.aspect_ratio = (1, 1) local_size = 2 vertices_data = array.array( "f", [ # fmt: off -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, 0.0, # fmt: on ], ) nb_vertices = 4 input_vertices = ngl.BufferVec3(data=vertices_data, label="vertices") output_vertices = ngl.BufferVec3(data=vertices_data, label="vertices") input_block = ngl.Block(fields=[input_vertices], layout="std140") output_block = ngl.Block(fields=[output_vertices], layout="std140") rotate_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360) ] rotate = ngl.Rotate(ngl.Identity(), axis=(0, 0, 1), angle=ngl.AnimatedFloat(rotate_animkf)) transform = ngl.UniformMat4(transform=rotate) program = ngl.ComputeProgram(_ANIMATION_COMPUTE, workgroup_size=(local_size, local_size, 1)) program.update_properties(dst=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroup_count=(nb_vertices / (local_size**2), 1, 1), program=program) compute.update_resources(transform=transform, src=input_block, dst=output_block) quad_buffer = ngl.BufferVec3(block=output_block, block_field=0) geometry = ngl.Geometry(quad_buffer, topology="triangle_strip") program = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geometry, program) render.update_frag_resources(color=ngl.UniformVec3(value=COLORS.sgreen), opacity=ngl.UniformFloat(1)) children = (compute, render) if animate_pre_render else (render, compute) return ngl.Group(children=children)
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 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 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 _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 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 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 _transform_shape(cfg): w, h = 0.75, 0.45 geometry = ngl.Quad(corner=(-w/2., -h/2., 0), width=(w, 0, 0), height=(0, h, 0)) prog = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) render = ngl.Render(geometry, prog) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['rose'])) return render