.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_gallery/feature_demo/text_waterfall.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr__gallery_feature_demo_text_waterfall.py: Text waterfall ============== An example showing a waterfall of text. On the left it shows the contents of the glyph atlas. One goal of this example is to strain the text rendering to its limits. .. GENERATED FROM PYTHON SOURCE LINES 9-105 .. image-sg:: /_gallery/feature_demo/images/sphx_glr_text_waterfall_001.webp :alt: text waterfall :srcset: /_gallery/feature_demo/images/sphx_glr_text_waterfall_001.webp :class: sphx-glr-single-img .. code-block:: Python from rendercanvas.auto import RenderCanvas, loop import pygfx as gfx import numpy as np renderer = gfx.renderers.WgpuRenderer(RenderCanvas(size=(800, 400))) scene = gfx.Scene() glyph_atlas = gfx.utils.text.glyph_atlas glyph_atlas.clear_free_regions = True # So we can see regions being freed # Add background background = gfx.Background.from_color("#dde", "#fff") scene.add(background) # Add an image that shows the glyph atlas atlas_viewer = gfx.Mesh( gfx.plane_geometry(100, 100), gfx.MeshBasicMaterial(color="red"), ) scene.add(atlas_viewer) atlas_viewer.local.x = -50 camera = gfx.OrthographicCamera(200, 100) # Create a bunch of reusable text objects def character_generator(): pieces = gfx.font_manager.select_font(" ", gfx.font_manager.default_font_props) font = pieces[0][1] while True: for c in font.codepoints: yield chr(c) chargen = character_generator() live_objects = set() waiting_objects = set() text_material = gfx.TextMaterial(color="#06E") for _i in range(100): obj = gfx.Text(text=" ", font_size=18, screen_space=True, material=text_material) scene.add(obj) waiting_objects.add(obj) obj.local.y = -999 # The animate function makes the text objects fall down, and update the objects # with a new character once they start their fall again. # Until we have real garbage collection for glyphs, we fake it here. def animate(): garbage_collect = True # Let them fall for obj in list(live_objects): obj.local.y -= obj.fall_speed if obj.local.y < -60: live_objects.discard(obj) waiting_objects.add(obj) if garbage_collect: all_indices = set() for x in live_objects: atlas_indices = x.geometry.glyph_data.data["atlas_index"] all_indices.update(int(index) for index in atlas_indices) for index in obj.geometry.glyph_data.data["atlas_index"]: index = int(index) if index not in all_indices: glyph_atlas.free_region(index) # Drop new objects if waiting_objects: obj = waiting_objects.pop() live_objects.add(obj) obj.local.y = 50 obj.local.x = np.random.uniform(0, 100) obj.set_text(next(chargen)) obj.fall_speed = np.random.uniform(1, 4) # Update the image if atlas_viewer.material.map is not glyph_atlas.texture: atlas_viewer.material.map = glyph_atlas.texture # Render renderer.render(scene, camera) renderer.request_draw() if __name__ == "__main__": renderer.request_draw(animate) loop.run() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 16.334 seconds) .. _sphx_glr_download__gallery_feature_demo_text_waterfall.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: text_waterfall.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: text_waterfall.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: text_waterfall.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_ .. only:: html Interactive example ------------------- Try this example in your browser using Pyodide. Might not work with all examples and all devices. Check the output and your browser's console for details. .. raw:: html