Background
Previous layer-based blit pipeline had two problems at once: alpha transparency composited incorrectly because per-layer surfaces were blitted independently, and the graph was redrawn from scratch every frame even when nothing changed except the camera.
Proposed Changes
- Transparency correctness falls out naturally once all artists draw onto a single SRCALPHA surface in z-order.
- Rendering optimization: do not redraw the graph (the expensive artist) when it hasn't actually changed, and skip work that isn't visible.
Implementation Approach
- Single render surface, layers as z-order only one _render_surface (SRCALPHA) + one _cache_surface.
Drop _surface_dict. Layers become a sort key, not a draw target.
- Per-artist RGBA cache
will_draw=False artists store their rendered output as (rgb, alpha, camera_state). Every frame = 1 blit instead of full redraw.
Generic by will_draw flag — graph happens to be the first user, but no graph-specific code in the render loop.
- Reuse cache across camera moves
Pan: offset-blit the cache by pixel delta. Full rebuild only if delta > screen/4.
Zoom: smoothscale the cache within [0.9, 1.11] zoom ratio. Rebuild outside.
Strip redraw: newly exposed edges after pan/zoom are filled by overriding culling bounds to the strip's world rect + set_clip + render_single_artist. Only the strip is redrawn, not the full graph.
- Spatial index for graph draws
GraphSpatialIndex (uniform grid) + GraphRenderCache with pre-computed edge_line_points.
render_graph queries only nodes/edges inside current culling bounds — critical for making strip redraw cheap enough to hit frame rate.
Relevant Files (expected)
- pygame_engine.py
- render_manager.py
Closes
Background
Previous layer-based blit pipeline had two problems at once: alpha transparency composited incorrectly because per-layer surfaces were blitted independently, and the graph was redrawn from scratch every frame even when nothing changed except the camera.
Proposed Changes
Implementation Approach
Drop _surface_dict. Layers become a sort key, not a draw target.
will_draw=False artists store their rendered output as (rgb, alpha, camera_state). Every frame = 1 blit instead of full redraw.
Generic by will_draw flag — graph happens to be the first user, but no graph-specific code in the render loop.
Pan: offset-blit the cache by pixel delta. Full rebuild only if delta > screen/4.
Zoom: smoothscale the cache within [0.9, 1.11] zoom ratio. Rebuild outside.
Strip redraw: newly exposed edges after pan/zoom are filled by overriding culling bounds to the strip's world rect + set_clip + render_single_artist. Only the strip is redrawn, not the full graph.
GraphSpatialIndex (uniform grid) + GraphRenderCache with pre-computed edge_line_points.
render_graph queries only nodes/edges inside current culling bounds — critical for making strip redraw cheap enough to hit frame rate.
Relevant Files (expected)
Closes