def _get_scene(geometry=None): program = ngl.Program(vertex=_vert, fragment=_frag) if geometry is None: geometry = ngl.Quad() scene = ngl.Render(geometry, program) scene.update_frag_resources(color=ngl.UniformVec4(value=(1.0, 1.0, 1.0, 1.0))) return scene
def shape_diamond_colormask(cfg): color_write_masks = ('r+g+b+a', 'r+g+a', 'g+b+a', 'r+b+a') geometry = ngl.Circle(npoints=5) 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['white'])) scenes = [ngl.GraphicConfig(render, color_write_mask=cwm) for cwm in color_write_masks] return autogrid_simple(scenes)
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 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' square_vertices = array.array('f') 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') 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]) 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) geom.set_topology('triangle_fan') 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 buffer_dove(cfg, bgcolor1=(.6, 0, 0, 1), bgcolor2=(.8, .8, 0, 1), bilinear_filtering=True): '''Blending of a Render using a Buffer as data source''' cfg.duration = 3. # Credits: https://icons8.com/icon/40514/dove 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((-.5, -.5, 0.1), (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()) render = ngl.Render(quad, program, label='dove') render.update_frag_resources(tex0=img_tex) render = ngl.GraphicConfig(render, blend=True, blend_src_factor='src_alpha', blend_dst_factor='one_minus_src_alpha', blend_src_factor_a='zero', blend_dst_factor_a='one') prog_bg = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) shape_bg = ngl.Circle(radius=.6, npoints=256) render_bg = ngl.Render(shape_bg, prog_bg, label='background') color_animkf = [ ngl.AnimKeyFrameVec4(0, bgcolor1), ngl.AnimKeyFrameVec4(cfg.duration / 2.0, bgcolor2), ngl.AnimKeyFrameVec4(cfg.duration, bgcolor1) ] ucolor = ngl.AnimatedVec4(color_animkf) render_bg.update_frag_resources(color=ucolor) return ngl.Group(children=(render_bg, render))
def animated_camera(cfg, rotate=True): '''Animated camera around a scene''' g = ngl.Group() q = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) node = ngl.Render(q, program) node.update_textures(tex0=t) g.add_children(node) translate = ngl.Translate(node, vector=(-0.6, 0.8, -1)) g.add_children(translate) translate = ngl.Translate(node, vector=(0.6, 0.8, -1)) g.add_children(translate) translate = ngl.Translate(node, vector=(-0.6, -0.5, -1)) g.add_children(translate) translate = ngl.Translate(node, vector=(0.6, -0.5, -1)) g.add_children(translate) g = ngl.GraphicConfig(g, depth_test=True) camera = ngl.Camera(g) camera.set_eye(0, 0, 2) 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(0.1, 10.0) tr_animkf = [ ngl.AnimKeyFrameVec3(0, (0.0, 0.0, 0.0)), ngl.AnimKeyFrameVec3(10, (0.0, 0.0, 3.0), 'exp_out') ] node = ngl.Translate(ngl.Identity(), anim=ngl.AnimatedVec3(tr_animkf)) if rotate: rot_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360, 'exp_out') ] node = ngl.Rotate(node, axis=(0, 1, 0), anim=ngl.AnimatedFloat(rot_animkf)) camera.set_eye_transform(node) fov_animkf = [ ngl.AnimKeyFrameFloat(0.5, 60.0), ngl.AnimKeyFrameFloat(cfg.duration, 45.0, 'exp_out') ] camera.set_fov_anim(ngl.AnimatedFloat(fov_animkf)) return camera
def _get_scene( self, file0, file1, diff_mode=False, split=(0.5, 0.5), vertical_split=True, show_r=True, show_g=True, show_b=True, show_a=True, premultiplied=False, threshold=0.001, ): vert = pkgutil.get_data("pynodegl_utils.diff.shaders", "diff.vert") frag = pkgutil.get_data("pynodegl_utils.diff.shaders", "diff.frag") assert vert is not None and frag is not None quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) prog = ngl.Program(vertex=vert.decode(), fragment=frag.decode()) prog.update_vert_out_vars( uv=ngl.IOVec2(), tex0_coord=ngl.IOVec2(), tex1_coord=ngl.IOVec2(), ) scene = ngl.Render(quad, prog) scene.update_frag_resources( tex0=ngl.Texture2D(data_src=ngl.Media(file0)), tex1=ngl.Texture2D(data_src=ngl.Media(file1)), split=ngl.UniformVec2(split, live_id="split"), diff_mode=ngl.UniformBool(diff_mode, live_id="diff_mode"), vertical_split=ngl.UniformBool(vertical_split, live_id="vertical_split"), show_r=ngl.UniformBool(show_r, live_id="show_r"), show_g=ngl.UniformBool(show_g, live_id="show_g"), show_b=ngl.UniformBool(show_b, live_id="show_b"), show_a=ngl.UniformBool(show_a, live_id="show_a"), premultiplied=ngl.UniformBool(premultiplied, live_id="premultiplied"), threshold=ngl.UniformFloat(threshold, live_id="threshold", live_max=0.1), ) scene.update_vert_resources( reframing_scale=ngl.UniformFloat( self._reframing_scale, live_id="reframing_scale", live_min=self._MIN_SCALE, live_max=self._MAX_SCALE, ), reframing_off=ngl.UniformVec2( self._reframing_off, live_id="reframing_off", live_min=(-self._MAX_SCALE, -self._MAX_SCALE), live_max=(self._MAX_SCALE, self._MAX_SCALE), ), ) return scene
def histogram(cfg): """Histogram using compute shaders""" m0 = cfg.medias[0] cfg.duration = m0.duration cfg.aspect_ratio = (m0.width, m0.height) g = ngl.Group() m = ngl.Media(cfg.medias[0].filename) t = ngl.Texture2D(data_src=m) h = ngl.Block(label="histogram_block", layout="std430") h.add_fields( ngl.BufferUInt(256, label="r"), ngl.BufferUInt(256, label="g"), ngl.BufferUInt(256, label="b"), ngl.UniformUInt(label="maximum"), ) r = ngl.RenderTexture(t) proxy_size = 128 proxy = ngl.Texture2D(width=proxy_size, height=proxy_size) rtt = ngl.RenderToTexture(r) rtt.add_color_textures(proxy) g.add_children(rtt) compute_program = ngl.ComputeProgram(cfg.get_comp("histogram-clear"), workgroup_size=(1, 1, 1)) compute_program.update_properties(hist=ngl.ResourceProps(writable=True)) compute = ngl.Compute(workgroup_count=(256, 1, 1), program=compute_program, label="histogram-clear") compute.update_resources(hist=h) g.add_children(compute) local_size = 8 group_size = proxy_size / local_size compute_program = ngl.ComputeProgram(cfg.get_comp("histogram-exec"), workgroup_size=(local_size, local_size, 1)) compute = ngl.Compute(workgroup_count=(group_size, group_size, 1), program=compute_program, label="histogram-exec") compute.update_resources(hist=h, source=proxy) compute_program.update_properties(hist=ngl.ResourceProps(writable=True)) compute_program.update_properties(source=ngl.ResourceProps(as_image=True)) g.add_children(compute) q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) p = ngl.Program(vertex=cfg.get_vert("histogram-display"), fragment=cfg.get_frag("histogram-display")) p.update_vert_out_vars(var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) render = ngl.Render(q, p) render.update_frag_resources(tex0=t, hist=h) g.add_children(render) return g
def stl(cfg, stl=None, scale=0.8): """Load and display a sphere generated with OpenSCAD""" if stl is None: # generated with: echo 'sphere($fn=15);'>sphere.scad; openscad sphere.scad -o sphere.stl stl = op.join(op.dirname(__file__), "data", "sphere.stl") normals_data = array.array("f") vertices_data = array.array("f") solid_label = None normal = None with open(stl) as fp: for line in fp.readlines(): line = line.strip() if line.startswith("solid"): solid_label = line.split(None, 1)[1] elif line.startswith("facet normal"): _, _, normal = line.split(None, 2) normal = [float(f) for f in normal.split()] elif normal and line.startswith("vertex"): _, vertex = line.split(None, 1) vertex = [float(f) for f in vertex.split()] normals_data.extend(normal) vertices_data.extend(vertex) vertices = ngl.BufferVec3(data=vertices_data) normals = ngl.BufferVec3(data=normals_data) g = ngl.Geometry(vertices=vertices, normals=normals) p = ngl.Program(vertex=cfg.get_vert("colored-normals"), fragment=cfg.get_frag("colored-normals")) p.update_vert_out_vars(var_normal=ngl.IOVec3(), var_uvcoord=ngl.IOVec2(), var_tex0_coord=ngl.IOVec2()) solid = ngl.Render(g, p, label=solid_label) solid = ngl.GraphicConfig(solid, depth_test=True) solid = ngl.Scale(solid, [scale] * 3) 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)] solid = ngl.Rotate(solid, axis=axis, angle=rot_animkf) camera = ngl.Camera(solid) camera.set_eye(2.0, 2.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) return camera
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 _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_uniforms(color=ngl.UniformVec4(value=COLORS['rose'])) return render
def api_shader_init_fail(width=320, height=240): ctx = ngl.Context() ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend) assert ret == 0 render = ngl.Render(ngl.Quad(), ngl.Program(vertex="<bug>", fragment="<bug>")) assert ctx.set_scene(render) != 0 assert ctx.set_scene(render) != 0 # another try to make sure the state stays consistent assert ctx.draw(0) == 0
def _render_buffer(cfg, w, h): n = w * h data = array.array('B', [i * 255 // n for i in range(n)]) buf = ngl.BufferUByte(data=data) texture = ngl.Texture2D(width=w, height=h, data_src=buf) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=cfg.get_frag('texture')) render = ngl.Render(ngl.Quad(), program) render.update_textures(tex0=texture) return render
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_render(cfg, quad, fields, block_definition, color_definition, block_fields, color_fields, layout, debug_positions=False): func_calls = [] func_definitions = [] for i, field in enumerate(fields): field_len = field.get('len') func_calls.append('get_color_{}(w, h, 0.0, {:f} * h)'.format( field['name'], i)) func_definitions.append( _get_display_glsl_func(layout, field['name'], field['type'], field_len=field_len)) frag_data = dict( func_definitions='\n'.join(func_definitions), func_calls=' + '.join(func_calls), ) fragment = _FIELDS_FRAG % frag_data vertex = _FIELDS_VERT program = ngl.Program(vertex=vertex, fragment=fragment) program.update_vert_out_vars(var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) if isinstance(color_fields, dict): assert isinstance(block_fields, dict) field_names = {f['name'] for f in fields} d = {} d.update(('color_' + n, u) for (n, u) in color_fields.items() if n in field_names) d.update(('field_' + n, u) for (n, u) in block_fields.items() if n in field_names) render.update_frag_resources(**d) else: render.update_frag_resources(fields=block_fields, colors=color_fields) render.update_frag_resources(nb_fields=ngl.UniformInt(len(fields))) if debug_positions: debug_points = _get_debug_positions_from_fields(fields) dbg_circles = get_debug_points(cfg, debug_points, text_size=(.2, .1)) g = ngl.Group(children=(render, dbg_circles)) return g return render
def _get_blending_base_objects(cfg): circle = ngl.Circle(radius=_CIRCLE_RADIUS, npoints=100) prog = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) positions = _equilateral_triangle_coords(_CIRCLE_RADIUS * 2.0 / 3.0) colored_circles = ngl.Group(label='colored circles') for position, color in zip(positions, _CIRCLES_COLORS): render = ngl.Render(circle, prog) render.update_frag_resources(color=ngl.UniformVec4(value=color)) render = ngl.Translate(render, position) colored_circles.add_children(render) return colored_circles, circle, prog, positions
def _get_data_streamed_buffer_vec4_scene(cfg, scale, show_dbg_points): duration = _N cfg.duration = duration * scale cfg.aspect_ratio = (1, 1) size, data_size, = _N, _N * _N time_anim = None if scale != 1: kfs = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, duration), ] time_anim = ngl.AnimatedTime(kfs) pts_data = array.array('q') assert pts_data.itemsize == 8 for i in range(duration): offset = 10000 if i == 0 else 0 pts_data.extend([i * 1000000 + offset]) vec4_data = array.array('f') for i in range(duration): for j in range(data_size): v = i / float(duration) + j / float(data_size * duration) vec4_data.extend([v, v, v, v]) pts_buffer = ngl.BufferInt64(data=pts_data) vec4_buffer = ngl.BufferVec4(data=vec4_data) streamed_buffer = ngl.StreamedBufferVec4(data_size, pts_buffer, vec4_buffer, time_anim=time_anim, label='data') streamed_block = ngl.Block(layout='std140', label='streamed_block', fields=(streamed_buffer, )) shader_params = dict(data_size=data_size, size=size) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) program = ngl.Program( vertex=_RENDER_STREAMEDBUFFER_VERT, fragment=_RENDER_STREAMEDBUFFER_FRAG % shader_params, ) program.update_vert_out_vars(var_uvcoord=ngl.IOVec2()) render = ngl.Render(quad, program) render.update_frag_resources(streamed=streamed_block) group = ngl.Group(children=(render, )) if show_dbg_points: cuepoints = _get_data_streamed_buffer_cuepoints() group.add_children(get_debug_points(cfg, cuepoints)) return group
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 transform_animated_camera(cfg): cfg.duration = 5. g = ngl.Group() elems = ( ('red', None), ('yellow', (-0.6, 0.8, -1)), ('green', (0.6, 0.8, -1)), ('cyan', (-0.6, -0.5, -1)), ('magenta', (0.6, -0.5, -1)), ) quad = ngl.Quad((-0.5, -0.5, 0), (1, 0, 0), (0, 1, 0)) prog = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) for color, vector in elems: node = ngl.Render(quad, prog) node.update_uniforms(color=ngl.UniformVec4(value=COLORS[color])) if vector: node = ngl.Translate(node, vector=vector) g.add_children(node) g = ngl.GraphicConfig(g, depth_test=True) camera = ngl.Camera(g) camera.set_eye(0, 0, 2) 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(0.1, 10.0) tr_animkf = [ ngl.AnimKeyFrameVec3(0, (0.0, 0.0, 0.0)), ngl.AnimKeyFrameVec3(cfg.duration, (0.0, 0.0, 3.0)) ] eye_transform = ngl.Translate(ngl.Identity(), anim=ngl.AnimatedVec3(tr_animkf)) rot_animkf = [ ngl.AnimKeyFrameFloat(0, 0), ngl.AnimKeyFrameFloat(cfg.duration, 360) ] eye_transform = ngl.Rotate(eye_transform, axis=(0, 1, 0), anim=ngl.AnimatedFloat(rot_animkf)) camera.set_eye_transform(eye_transform) fov_animkf = [ ngl.AnimKeyFrameFloat(0.5, 60.0), ngl.AnimKeyFrameFloat(cfg.duration, 45.0) ] camera.set_fov_anim(ngl.AnimatedFloat(fov_animkf)) return camera
def compute_animation(cfg): cfg.duration = 5 cfg.aspect_ratio = (1, 1) local_size = 2 vertices_data = array.array('f', [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, 0.0, ]) 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), anim=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.UniformVec4(value=COLORS['sgreen'])) return ngl.Group(children=(compute, render))
def _render_buffer(cfg, w, h): n = w * h data = array.array('B', [i * 255 // n for i in range(n)]) buf = ngl.BufferUByte(data=data) texture = ngl.Texture2D(width=w, height=h, data_src=buf) program = ngl.Program(vertex=cfg.get_vert('texture'), fragment=_RENDER_BUFFER_FRAG) program.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) render = ngl.Render(ngl.Quad(), program) render.update_frag_resources(tex0=texture) return render
def _get_live_shared_uniform_scene(cfg, color, debug_positions): program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) group = ngl.Group() for i in range(2): quad = ngl.Quad((-1 + i, -1 + i, 0), (1, 0, 0), (0, 1, 0)) render = ngl.Render(quad, program) render.update_frag_resources(color=color) group.add_children(render) if debug_positions: group.add_children(get_debug_points(cfg, _SHARED_UNIFORM_CUEPOINTS)) return group
def _get_texture_cubemap_from_mrt_scene(cfg, samples=0): glsl_version = '300 es' if cfg.backend == 'gles' else '330' glsl_header = '#version %s\n' % glsl_version render_to_cubemap_vert = glsl_header + _RENDER_TO_CUBEMAP_VERT render_to_cubemap_frag = glsl_header + _RENDER_TO_CUBEMAP_FRAG program = ngl.Program(vertex=render_to_cubemap_vert, fragment=render_to_cubemap_frag) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) render = ngl.Render(quad, program) cube = ngl.TextureCube(size=64, min_filter="linear", mag_filter="linear") rtt = ngl.RenderToTexture(render, [cube], samples=samples) render_cubemap_vert = glsl_header + _RENDER_CUBEMAP_VERT render_cubemap_frag = glsl_header + _RENDER_CUBEMAP_FRAG program = ngl.Program(vertex=render_cubemap_vert, fragment=render_cubemap_frag) render = ngl.Render(quad, program) render.update_textures(tex0=cube) return ngl.Group(children=(rtt, render))
def texture_scissor(cfg): cfg.aspect_ratio = (1, 1) quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) color = ngl.UniformVec4(COLORS['orange']) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) render = ngl.Render(quad, program) render.update_uniforms(color=color) graphic_config = ngl.GraphicConfig(render, scissor_test=True, scissor=(32, 32, 32, 32)) texture = ngl.Texture2D(width=64, height=64) rtt = ngl.RenderToTexture(graphic_config, [texture]) 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 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'), fragment=cfg.get_frag('texture')) p.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(), var_uvcoord=ngl.IOVec2()) 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.AnimatedFloat(utime_animkf) render = ngl.Render(q, p, nb_instances=dim**2) render.update_frag_resources(tex0=t) render.update_vert_resources(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 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 texture_clear_and_scissor(cfg): quad = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0)) color = ngl.UniformVec4(COLORS['white']) program = ngl.Program(vertex=cfg.get_vert('color'), fragment=cfg.get_frag('color')) render = ngl.Render(quad, program) render.update_uniforms(color=color) graphic_config = ngl.GraphicConfig(render, scissor_test=True, scissor=(0, 0, 0, 0)) texture = ngl.Texture2D(width=64, height=64) rtt = ngl.RenderToTexture(ngl.Identity(), [texture], clear_color=COLORS['orange']) 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=(graphic_config, rtt, render))
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 rtt_load_attachment_nested(cfg): scene = _rtt_load_attachment(cfg) texture = ngl.Texture2D(width=16, height=16) rtt = ngl.RenderToTexture(scene, [texture]) 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()) foreground = ngl.Render(quad, program) foreground.update_frag_resources(tex0=texture) return ngl.Group(children=(rtt, foreground))
def get_render(cfg, quad, fields, block_definition, color_definition, block_fields, color_fields, layout, debug_positions=False): func_calls = [] func_definitions = [] for i, field in enumerate(fields): is_array = 'len' in field func_calls.append('get_color_%s(w, h, 0.0, %f * h)' % (field['name'], i)) func_definitions.append(_get_display_glsl_func(layout, field['name'], field['type'], is_array=is_array)) frag_data = dict( block_definition=_get_glsl_fields_definition(1, layout, 'fields', block_definition), color_definition=_get_glsl_fields_definition(2, layout, 'colors', color_definition), layout=layout, func_definitions='\n'.join(func_definitions), func_calls=' + '.join(func_calls), ) if layout == 'std430': shader_version = '310 es' if cfg.backend == 'gles' else '430' else: shader_version = '300 es' if cfg.backend == 'gles' else '330' header = '#version %s\n' % shader_version fragment = header + _FIELDS_FRAG % frag_data vertex = header + _FIELDS_VERT program = ngl.Program(vertex=vertex, fragment=fragment) render = ngl.Render(quad, program) if isinstance(color_fields, dict): assert isinstance(block_fields, dict) field_names = set(f['name'] for f in fields) d = {} d.update(('color_' + n, u) for (n, u) in color_fields.items() if n in field_names) d.update(('field_' + n, u) for (n, u) in block_fields.items() if n in field_names) render.update_uniforms(**d) else: render.update_blocks(fields_block=block_fields, colors_block=color_fields) render.update_uniforms(nb_fields=ngl.UniformInt(len(fields))) if debug_positions: debug_points = _get_debug_positions_from_fields(fields) dbg_circles = get_debug_points(cfg, debug_points, text_size=(.2, .1)) g = ngl.Group(children=(render, dbg_circles)) return g return render