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 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 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 compute_particles(cfg): cfg.duration = 10 workgroups = (2, 1, 4) local_size = (4, 4, 1) nb_particles = workgroups[0] * workgroups[1] * workgroups[2] * local_size[ 0] * local_size[1] * local_size[2] positions = array.array("f") velocities = array.array("f") for i in range(nb_particles): positions.extend([ cfg.rng.uniform(-2.0, 1.0), cfg.rng.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ cfg.rng.uniform(1.0, 2.0), cfg.rng.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions, label="positions"), ngl.BufferVec2(data=velocities, label="velocities"), ], layout="std430", ) opositions = ngl.Block( fields=[ngl.BufferVec3(count=nb_particles, label="positions")], layout="std140") animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) program = ngl.ComputeProgram(_PARTICULES_COMPUTE, workgroup_size=local_size) program.update_properties(odata=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroups, program) compute.update_resources(time=time, duration=duration, idata=ipositions, odata=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=_PARTICULES_VERT, fragment=cfg.get_frag("color")) render = ngl.Render(circle, program, nb_instances=nb_particles) render.update_frag_resources(color=ngl.UniformVec3(value=COLORS.sgreen), opacity=ngl.UniformFloat(1)) render.update_vert_resources(data=opositions) group = ngl.Group() group.add_children(compute, render) return group
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 compute_particules(cfg): random.seed(0) cfg.duration = 10 local_size = 4 nb_particules = 128 shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_data = dict( version=shader_version, local_size=local_size, nb_particules=nb_particules, ) compute_shader = _PARTICULES_COMPUTE % shader_data vertex_shader = _PARTICULES_VERT % shader_data fragment_shader = _PARTICULES_FRAG % shader_data positions = array.array('f') velocities = array.array('f') for i in range(nb_particules): positions.extend([ random.uniform(-2.0, 1.0), random.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(1.0, 2.0), random.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions), ngl.BufferVec2(data=velocities), ], layout='std430', ) opositions = ngl.Block(fields=[ngl.BufferVec3(count=nb_particules)], layout='std430') animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) group_size = nb_particules / local_size program = ngl.ComputeProgram(compute_shader) compute = ngl.Compute(nb_particules, 1, 1, program) compute.update_uniforms(time=time, duration=duration) compute.update_blocks(ipositions_buffer=ipositions, opositions_buffer=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=vertex_shader, fragment=fragment_shader) render = ngl.Render(circle, program, nb_instances=nb_particules) render.update_uniforms(color=ngl.UniformVec4(value=COLORS['sgreen'])) render.update_blocks(positions_buffer=opositions) group = ngl.Group() group.add_children(compute, render) return group
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 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 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 _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 triangle(cfg, size=4 / 3): """Rotating triangle with edge coloring specified in a vertex attribute""" cfg.duration = 3.0 cfg.aspect_ratio = (1, 1) colors_data = array.array("f", [0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0]) colors_buffer = ngl.BufferVec3(data=colors_data) p0, p1, p2 = equilateral_triangle_coords(size) triangle = ngl.Triangle(p0, p1, p2) p = ngl.Program(fragment=cfg.get_frag("color"), vertex=cfg.get_vert("triangle")) p.update_vert_out_vars(color=ngl.IOVec3()) node = ngl.Render(triangle, p) node.update_attributes(edge_color=colors_buffer) node.update_frag_resources(opacity=ngl.UniformFloat(1)) animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration / 3.0, -360 / 3.0, "exp_in_out"), ngl.AnimKeyFrameFloat(2 * cfg.duration / 3.0, -2 * 360 / 3.0, "exp_in_out"), ngl.AnimKeyFrameFloat(cfg.duration, -360, "exp_in_out"), ] node = ngl.Rotate(node, angle=ngl.AnimatedFloat(animkf)) return node
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 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)) p = ngl.Program() 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.AnimatedFloat(animkf_m2)) t1 = ngl.Texture2D(data_src=m1, label='texture #1') t2 = ngl.Texture2D(data_src=m2, label='texture #2') render1 = ngl.Render(q, p, label='render #1') render1.update_textures(tex0=t1) render2 = ngl.Render(q, p, 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 = ngl.UniformFloat(value=1.0, 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 compute_particules(cfg): random.seed(0) cfg.duration = 10 local_size = 4 nb_particules = 128 positions = array.array('f') velocities = array.array('f') for i in range(nb_particules): positions.extend([ random.uniform(-2.0, 1.0), random.uniform(-1.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(1.0, 2.0), random.uniform(0.5, 1.5), ]) ipositions = ngl.Block( fields=[ ngl.BufferVec3(data=positions, label='positions'), ngl.BufferVec2(data=velocities, label='velocities'), ], layout='std430', ) opositions = ngl.Block( fields=[ngl.BufferVec3(count=nb_particules, label='positions')], layout='std430') animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1.0), ] time = ngl.AnimatedFloat(animkf) duration = ngl.UniformFloat(cfg.duration) group_size = nb_particules / local_size program = ngl.ComputeProgram(_PARTICULES_COMPUTE % dict(local_size=local_size)) compute = ngl.Compute(nb_particules, 1, 1, program) compute.update_resources(time=time, duration=duration, idata=ipositions, odata=opositions) circle = ngl.Circle(radius=0.05) program = ngl.Program(vertex=_PARTICULES_VERT, fragment=cfg.get_frag('color')) render = ngl.Render(circle, program, nb_instances=nb_particules) render.update_frag_resources(color=ngl.UniformVec4(value=COLORS['sgreen'])) render.update_vert_resources(data=opositions) group = ngl.Group() group.add_children(compute, render) return group
def shape_triangles_mat4_attribute(cfg): cfg.aspect_ratio = (1, 1) p0, p1, p2 = equilateral_triangle_coords(1) geometry = ngl.Triangle(p0, p1, p2) matrices = ngl.BufferMat4(data=array.array( "f", [ # fmt: off 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0, 1.0, # fmt: on ], )) program = ngl.Program( vertex=TRIANGLES_MAT4_ATTRIBUTE_VERT, fragment=cfg.get_frag("color"), ) render = ngl.Render(geometry, program, nb_instances=2) render.update_instance_attributes(matrix=matrices) render.update_frag_resources(color=ngl.UniformVec3(value=COLORS.orange), opacity=ngl.UniformFloat(1)) return render
def cropboard(cfg, dim=15): '''Divided media using instancing draw and UV coords offsetting from a buffer''' m0 = cfg.medias[0] random.seed(0) cfg.duration = 10 cfg.aspect_ratio = (m0.width, m0.height) kw = kh = 1. / dim qw = qh = 2. / dim p = ngl.Program(vertex=cfg.get_vert('cropboard')) m = ngl.Media(m0.filename) t = ngl.Texture2D(data_src=m) uv_offset_buffer = array.array('f') translate_a_buffer = array.array('f') translate_b_buffer = array.array('f') q = ngl.Quad(corner=(0, 0, 0), width=(qw, 0, 0), height=(0, qh, 0), uv_corner=(0, 0), uv_width=(kw, 0), uv_height=(0, kh)) for y in range(dim): for x in range(dim): uv_offset = [x*kw, (y+1.)*kh - 1.] src = [random.uniform(-2, 2), random.uniform(-2, 2)] dst = [x*qw - 1., 1. - (y+1.)*qh] uv_offset_buffer.extend(uv_offset) translate_a_buffer.extend(src) translate_b_buffer.extend(dst) utime_animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration*2/3., 1, 'exp_out')] utime = ngl.UniformFloat(anim=ngl.AnimatedFloat(utime_animkf)) render = ngl.Render(q, p, nb_instances=dim**2) render.update_textures(tex0=t) render.update_uniforms(time=utime) render.update_instance_attributes( uv_offset=ngl.BufferVec2(data=uv_offset_buffer), translate_a=ngl.BufferVec2(data=translate_a_buffer), translate_b=ngl.BufferVec2(data=translate_b_buffer), ) return render
def py_bindings_allow_node(): c = ngl.Camera(eye=(0, 1, 0)) assert c.set_eye(ngl.EvalVec3()) == 0 assert c.set_eye(1, 0, 0) == 0 c = ngl.Camera(eye=ngl.NoiseVec3()) assert c.set_eye(1, 0, 0) == 0 assert c.set_eye(ngl.UniformVec3()) == 0 r = ngl.Rotate(angle=30) assert r.set_angle(ngl.NoiseFloat()) == 0 assert r.set_angle(-45) == 0 r = ngl.Rotate(angle=ngl.EvalFloat()) assert r.set_angle(90) == 0 assert r.set_angle(ngl.UniformFloat()) == 0
def urchin(cfg, npoints=25): """Urchin with animated vertices""" cfg.duration = 5 cfg.aspect_ratio = (1, 1) def get_vertices(n, radius_func, offset=0.0): vertices = [] step = 2 * math.pi / n for i in range(n): angle = (i + offset) * step radius = radius_func() x, y = math.sin(angle) * radius, math.cos(angle) * radius vertices.append([x, y, 0]) return vertices k = 16 n, m = 0.1, 0.9 inner_rfunc = lambda: n inner_vertices = get_vertices(npoints, inner_rfunc) vdata = [] for i in range(k): outer_rfunc = lambda: cfg.rng.uniform(n, m) outer_vertices = get_vertices(npoints, outer_rfunc, offset=0.5) vertices_data = array.array("f") for inner_vertex, outer_vertex in zip(inner_vertices, outer_vertices): vertices_data.extend(inner_vertex + outer_vertex) vertices_data.extend(inner_vertices[0]) vdata.append(vertices_data) animkf = [] for i, v in enumerate(vdata + [vdata[0]]): animkf.append(ngl.AnimKeyFrameBuffer(i * cfg.duration / float(k), v)) vertices = ngl.AnimatedBufferVec3(animkf) geom = ngl.Geometry(vertices) geom.set_topology("line_strip") p = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geom, p) render.update_frag_resources(color=ngl.UniformVec3(value=(0.9, 0.1, 0.3)), opacity=ngl.UniformFloat(1)) return render
def py_bindings_dict(): foo = ngl.UniformVec3(value=(1, 2, 3), label="foo-node") assert foo.set_value(3, 2, 1) == 0 render = ngl.Render(vert_resources=dict(foo=foo)) assert render.set_label("r") == 0 # Delete the previous entry and add another ret = render.update_vert_resources( foo=None, bar=ngl.UniformFloat(value=4, label="bar-node"), ) assert ret == 0 # Update by using a dict ret = render.update_vert_resources( dict( foo=ngl.UniformVec2(), bar=ngl.EvalFloat(), )) assert ret == 0
def _data_vertex_and_fragment_blocks(cfg, layout): """ This test ensures that the block bindings are properly set by pgcraft when UBOs or SSBOs are bound to different stages. """ cfg.aspect_ratio = (1, 1) src = ngl.Block( fields=[ ngl.UniformVec3(value=COLORS.red, label="color"), ngl.UniformFloat(value=0.5, label="opacity"), ], layout="std140", ) dst = ngl.Block( fields=[ ngl.UniformVec3(value=COLORS.white, label="color"), ], layout=layout, ) vert = textwrap.dedent("""\ void main() { ngl_out_pos = ngl_projection_matrix * ngl_modelview_matrix * vec4(ngl_position, 1.0); var_src = vec4(src.color, 1.0) * src.opacity; } """) frag = textwrap.dedent("""\ void main() { vec3 color = var_src.rgb + (1.0 - var_src.a) * dst.color; ngl_out_color = vec4(color, 1.0); } """) program = ngl.Program(vertex=vert, fragment=frag) program.update_vert_out_vars(var_src=ngl.IOVec4(), ) geometry = ngl.Quad(corner=(-1, -1, 0), width=(2, 0, 0), height=(0, 2, 0)) render = ngl.Render(geometry, program) render.update_vert_resources(src=src) render.update_frag_resources(dst=dst) return render
def audiotex(cfg, freq_precision=7, overlay=0.6): '''FFT/Waves audio texture of the audio stream blended on top of the video stream''' media = cfg.medias[0] cfg.duration = media.duration cfg.aspect_ratio = (media.width, media.height) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) audio_m = ngl.Media(media.filename, audio_tex=1) audio_tex = ngl.Texture2D(data_src=audio_m) video_m = ngl.Media(media.filename) video_tex = ngl.Texture2D(data_src=video_m) p = ngl.Program(vertex=cfg.get_vert('dual-tex'), fragment=cfg.get_frag('audiotex')) render = ngl.Render(q, p) render.update_textures(tex0=audio_tex, tex1=video_tex) render.update_uniforms(overlay=ngl.UniformFloat(overlay)) render.update_uniforms(freq_precision=ngl.UniformInt(freq_precision)) return render
def audiotex(cfg, freq_precision=7, overlay=0.6): """FFT/Waves audio texture of the audio stream blended on top of the video stream""" media = cfg.medias[0] cfg.duration = media.duration cfg.aspect_ratio = (media.width, media.height) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) audio_m = ngl.Media(media.filename, audio_tex=1) audio_tex = ngl.Texture2D(data_src=audio_m) video_m = ngl.Media(media.filename) video_tex = ngl.Texture2D(data_src=video_m) p = ngl.Program(vertex=cfg.get_vert("dual-tex"), fragment=cfg.get_frag("audiotex")) p.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_tex1_coord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=audio_tex, tex1=video_tex) render.update_frag_resources(overlay=ngl.UniformFloat(overlay)) render.update_frag_resources(freq_precision=ngl.UniformInt(freq_precision)) return render
def shape_morphing(cfg, n=6): cfg.duration = 5.0 vertices_tl = _get_morphing_coordinates(cfg.rng, n, -1, 0) vertices_tr = _get_morphing_coordinates(cfg.rng, n, 0, 0) vertices_bl = _get_morphing_coordinates(cfg.rng, n, -1, -1) vertices_br = _get_morphing_coordinates(cfg.rng, n, 0, -1) vertices_animkf = [] for i, coords in enumerate( zip(vertices_tl, vertices_tr, vertices_bl, vertices_br)): flat_coords = list(itertools.chain(*coords)) coords_array = array.array("f", flat_coords) vertices_animkf.append( ngl.AnimKeyFrameBuffer(i * cfg.duration / (n - 1), coords_array)) vertices = ngl.AnimatedBufferVec3(vertices_animkf) geom = ngl.Geometry(vertices) geom.set_topology("triangle_strip") p = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geom, p) render.update_frag_resources(color=ngl.UniformVec3(COLORS.cyan), opacity=ngl.UniformFloat(1)) return render
def smptebars_glitch(cfg): """SMPTE bars glitching at irregular intervals""" cfg.duration = 15 cfg.aspect_ratio = (4, 3) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program(vertex=cfg.get_vert("smptebars"), fragment=cfg.get_frag("smptebars")) program.update_vert_out_vars(var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) freq = cfg.framerate[0] / cfg.framerate[1] + 1 render.update_frag_resources( active_noise=ngl.NoiseFloat(octaves=1), active_probability=ngl.UniformFloat(0.4), # glitch 40% of the time uv_noise_0=ngl.NoiseVec2(amplitude=0.05, frequency=freq, seed=1000 + 0), uv_noise_1=ngl.NoiseVec2(amplitude=0.05, frequency=freq, seed=1000 + 0x7FFF), uv_noise_2=ngl.NoiseVec2(amplitude=0.05, frequency=freq, seed=1000 + 0xFFFF), ) return render
def _shape_geometry(cfg, set_normals=False, set_indices=False): # Fake cube (3 faces only) obtained from: # echo 'cube();'>x.scad; openscad x.scad -o x.stl vertices = array.array( "f", [ x - 0.5 for x in [ # fmt: off 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, # fmt: on ] ], ) normals = array.array( "f", [ # fmt: off 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, # fmt: on ], ) vertices_buffer = ngl.BufferVec3(data=vertices) normals_buffer = ngl.BufferVec3(data=normals) cfg.aspect_ratio = (1, 1) geometry = ngl.Geometry(vertices=vertices_buffer) if set_normals: geometry.set_normals(normals_buffer) prog = ngl.Program(vertex=cfg.get_vert("colored-normals"), fragment=cfg.get_frag("colored-normals")) prog.update_vert_out_vars(var_normal=ngl.IOVec3()) render = ngl.Render(geometry, prog) else: prog = ngl.Program(vertex=cfg.get_vert("color"), fragment=cfg.get_frag("color")) render = ngl.Render(geometry, prog) render.update_frag_resources( color=ngl.UniformVec3(value=COLORS.magenta), opacity=ngl.UniformFloat(1)) if set_indices: indices = array.array("H", list(range(3 * 6))) indices_buffer = ngl.BufferUShort(data=indices) geometry.set_indices(indices_buffer) return ngl.Rotate(render, 45, axis=(1, 1, 1))
def api_livectls(): # Build a scene and extract its live controls rng = random.Random(0) scene = ngl.Group( children=( ngl.UniformBool(live_id="b"), ngl.UniformFloat(live_id="f"), ngl.UniformIVec3(live_id="iv3"), ngl.UserSwitch( ngl.Group( children=( ngl.UniformMat4(live_id="m4"), ngl.UniformColor(live_id="clr"), ngl.UniformQuat(as_mat4=True, live_id="rot"), ) ), live_id="switch", ), ngl.Text(live_id="txt"), ) ) livectls = ngl.get_livectls(scene) assert len(livectls) == 8 # Attach scene and run a dummy draw to make sure it's valid ctx = ngl.Context() ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend) assert ret == 0 assert ctx.set_scene(scene) == 0 assert ctx.draw(0) == 0 # Apply live changes on nodes previously tracked by get_livectls() values = dict( b=True, f=rng.uniform(-1, 1), iv3=[rng.randint(-100, 100) for i in range(3)], switch=False, m4=[rng.uniform(-1, 1) for i in range(16)], clr=(0.9, 0.3, 0.8), rot=(0.1, -0.2, 0.5, -0.3), txt="test string", ) for live_id, value in values.items(): node = livectls[live_id]["node"] node_type = livectls[live_id]["node_type"] assert node_type == node.__class__.__name__ if node_type == "UserSwitch": node.set_enabled(value) elif node_type == "Text": node.set_text(value) elif hasattr(value, "__iter__"): node.set_value(*value) else: node.set_value(value) # Detach scene from context and grab all live controls again assert ctx.set_scene(None) == 0 livectls = ngl.get_livectls(scene) # Inspect nodes to check if they were properly altered by the live changes for live_id, expected_value in values.items(): value = livectls[live_id]["val"] node_type = livectls[live_id]["node_type"] if node_type == "Text": assert value == expected_value, (value, expected_value) elif hasattr(value, "__iter__"): assert all(math.isclose(v, e, rel_tol=1e-6) for v, e in zip(value, expected_value)) else: assert math.isclose(value, expected_value, rel_tol=1e-6)
keyframes=_get_anim_kf(ngl.AnimKeyFrameBuffer, data)), animated_quat_mat4=lambda data: ngl.AnimatedQuat( keyframes=_get_anim_kf(ngl.AnimKeyFrameQuat, data), as_mat4=True), animated_quat_vec4=lambda data: ngl.AnimatedQuat( keyframes=_get_anim_kf(ngl.AnimKeyFrameQuat, data), as_mat4=False), array_float=lambda data: ngl.BufferFloat(data=data), array_int=lambda data: ngl.BufferInt(data=data), array_ivec2=lambda data: ngl.BufferIVec2(data=data), array_ivec3=lambda data: ngl.BufferIVec3(data=data), array_ivec4=lambda data: ngl.BufferIVec4(data=data), array_mat4=lambda data: ngl.BufferMat4(data=data), array_vec2=lambda data: ngl.BufferVec2(data=data), array_vec3=lambda data: ngl.BufferVec3(data=data), array_vec4=lambda data: ngl.BufferVec4(data=data), single_bool=lambda data: ngl.UniformBool(data), single_float=lambda data: ngl.UniformFloat(data), single_int=lambda data: ngl.UniformInt(data), single_ivec2=lambda data: ngl.UniformIVec2(data), single_ivec3=lambda data: ngl.UniformIVec3(data), single_ivec4=lambda data: ngl.UniformIVec4(data), single_uint=lambda data: ngl.UniformUInt(data), single_uvec2=lambda data: ngl.UniformUIVec2(data), single_uvec3=lambda data: ngl.UniformUIVec3(data), single_uvec4=lambda data: ngl.UniformUIVec4(data), single_mat4=lambda data: ngl.UniformMat4(data), single_quat_mat4=lambda data: ngl.UniformQuat(data, as_mat4=True), single_quat_vec4=lambda data: ngl.UniformQuat(data, as_mat4=False), single_vec2=lambda data: ngl.UniformVec2(data), single_vec3=lambda data: ngl.UniformVec3(data), single_vec4=lambda data: ngl.UniformVec4(data), )
def mountain(cfg, ndim=3, nb_layers=7, ref_color=(0.5, .75, .75, 1.0), nb_mountains=6): '''Mountain generated with a stack of noise shaders using Textures as random source''' random.seed(0) random_dim = 1 << ndim cfg.aspect_ratio = (16, 9) cfg.duration = nb_mountains ** 2 def get_rand(): return array.array('f', [random.uniform(0, 1) for x in range(random_dim)]) black, white = (0, 0, 0, 1), (1, 1, 1, 1) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) prog = ngl.Program(fragment=cfg.get_frag('mountain')) hscale = 1/2. mountains = [] for i in range(nb_mountains): yoffset = (nb_mountains-i-1)/float(nb_mountains-1) * (1.0 - hscale) if i < nb_mountains/2: c0, c1 = ref_color, white x = (i + 1) / float(nb_mountains/2 + 1) else: c0, c1 = black, ref_color x = (i - nb_mountains/2) / float((nb_mountains-1)/2) mcolor = [x*a + (1.0-x)*b for a, b in zip(c0, c1)] random_buf = ngl.BufferFloat(data=get_rand()) random_tex = ngl.Texture2D(data_src=random_buf, width=random_dim, height=1) utime_animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, i+1)] utime = ngl.AnimatedFloat(utime_animkf) uyoffset_animkf = [ngl.AnimKeyFrameFloat(0, yoffset/2.), ngl.AnimKeyFrameFloat(cfg.duration/2.0, yoffset), ngl.AnimKeyFrameFloat(cfg.duration, yoffset/2.)] uyoffset = ngl.AnimatedFloat(uyoffset_animkf) render = ngl.Render(quad, prog) render.update_textures(tex0=random_tex) render.update_uniforms(dim=ngl.UniformInt(random_dim)) render.update_uniforms(nb_layers=ngl.UniformInt(nb_layers)) render.update_uniforms(time=utime) render.update_uniforms(lacunarity=ngl.UniformFloat(2.0)) render.update_uniforms(gain=ngl.UniformFloat(0.5)) render.update_uniforms(mcolor=ngl.UniformVec4(mcolor)) render.update_uniforms(yoffset=uyoffset) render.update_uniforms(hscale=ngl.UniformFloat(hscale)) mountains.append(render) prog = ngl.Program(fragment=cfg.get_frag('color')) sky = ngl.Render(quad, prog) sky.update_uniforms(color=ngl.UniformVec4(white)) group = ngl.Group(children=[sky] + mountains) blend = ngl.GraphicConfig(group, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one') return blend
def _get_cube_side(texture, program, corner, width, height, color): render = ngl.Render(ngl.Quad(corner, width, height), program) render.update_textures(tex0=texture) render.update_uniforms(blend_color=ngl.UniformVec3(value=color)) render.update_uniforms(mix_factor=ngl.UniformFloat(value=0.2)) return render
def particules(cfg, particules=32): '''Particules demo using compute shaders and instancing''' random.seed(0) shader_version = '310 es' if cfg.backend == 'gles' else '430' shader_header = '#version %s\n' % shader_version compute_shader = shader_header + cfg.get_comp('particules') vertex_shader = shader_header + cfg.get_vert('particules') fragment_shader = shader_header + cfg.get_frag('particules') cfg.duration = 6 x = 64 p = x * particules positions = array.array('f') velocities = array.array('f') for i in range(p): positions.extend([ random.uniform(-1.0, 1.0), random.uniform(0.0, 1.0), 0.0, ]) velocities.extend([ random.uniform(-0.01, 0.01), random.uniform(-0.05, 0.05), ]) ipositions = ngl.Block(fields=[ngl.BufferVec3(data=positions)], layout='std430') ivelocities = ngl.Block(fields=[ngl.BufferVec2(data=velocities)], layout='std430') opositions = ngl.Block(fields=[ngl.BufferVec3(count=p)], layout='std430') animkf = [ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 1)] utime = ngl.AnimatedFloat(animkf) uduration = ngl.UniformFloat(cfg.duration) cp = ngl.ComputeProgram(compute_shader) c = ngl.Compute(x, particules, 1, cp) c.update_uniforms( time=utime, duration=uduration, ) c.update_blocks( ipositions_buffer=ipositions, ivelocities_buffer=ivelocities, opositions_buffer=opositions, ) quad_width = 0.01 quad = ngl.Quad( corner=(-quad_width/2, -quad_width/2, 0), width=(quad_width, 0, 0), height=(0, quad_width, 0) ) p = ngl.Program( vertex=vertex_shader, fragment=fragment_shader, ) r = ngl.Render(quad, p, nb_instances=particules) r.update_uniforms(color=ngl.UniformVec4(value=(0, .6, .8, .9))) r.update_blocks(positions_buffer=opositions) r = ngl.GraphicConfig(r, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one') g = ngl.Group() g.add_children(c, r) return ngl.Camera(g)