Source code for mini_arcade_core.engine.render.pipeline

"""
Render pipeline module.
Defines the RenderPipeline class for rendering RenderPackets.
"""

# Justification: This code is duplicated in multiple places for clarity and separation
# of concerns.
# try:
#     for op in packet.ops:
#         op(backend)
# finally:
#     backend.clear_clip_rect()
#     backend.clear_viewport_transform() (duplicate-code)
# pylint: disable=duplicate-code

from __future__ import annotations

from dataclasses import dataclass, field

from mini_arcade_core.backend import Backend
from mini_arcade_core.engine.render.camera import viewport_transform_for_packet
from mini_arcade_core.engine.render.context import RenderContext
from mini_arcade_core.engine.render.frame_packet import FramePacket
from mini_arcade_core.engine.render.packet import RenderPacket
from mini_arcade_core.engine.render.passes.base import RenderPass
from mini_arcade_core.engine.render.passes.begin_frame import BeginFramePass
from mini_arcade_core.engine.render.passes.end_frame import EndFramePass
from mini_arcade_core.engine.render.passes.lighting import LightingPass
from mini_arcade_core.engine.render.passes.postfx import PostFXPass
from mini_arcade_core.engine.render.passes.ui import UIPass
from mini_arcade_core.engine.render.passes.world import WorldPass
from mini_arcade_core.engine.render.viewport import ViewportState


[docs] @dataclass class RenderPipeline: """ Minimal pipeline for v1. Later you can expand this into passes: - build draw list - cull - sort - backend draw pass :cvar passes: list[RenderPass]: List of render passes to execute in order. """ passes: list[RenderPass] = field( default_factory=lambda: [ BeginFramePass(), WorldPass(), LightingPass(), UIPass(), PostFXPass(), EndFramePass(), ] )
[docs] def render_frame( self, backend: Backend, ctx: RenderContext, packets: list[FramePacket] ): """ Render a frame using the provided Backend, RenderContext, and list of FramePackets. :param backend: Backend to use for rendering. :type backend: Backend :param ctx: RenderContext containing rendering state. :type ctx: RenderContext :param packets: List of FramePackets to render. :type packets: list[FramePacket] """ for p in self.passes: p.run(backend, ctx, packets)
[docs] def draw_packet( self, backend: Backend, packet: RenderPacket, viewport_state: ViewportState, ): """ Draw the given RenderPacket using the provided Backend. :param backend: Backend to use for drawing. :type backend: Backend :param packet: RenderPacket to draw. :type packet: RenderPacket """ if not packet: return world_transform = viewport_transform_for_packet(viewport_state, packet) backend.set_viewport_transform( viewport_state.offset_x, viewport_state.offset_y, viewport_state.scale, ) backend.render.set_clip_rect( 0, 0, viewport_state.virtual_w, viewport_state.virtual_h, ) try: backend.set_viewport_transform( world_transform.ox, world_transform.oy, world_transform.s, ) for op in packet.ops: op(backend) finally: backend.render.clear_clip_rect() backend.clear_viewport_transform()