arcane_engine/renderer/
mod.rs1mod gpu;
2mod sprite;
3mod texture;
4mod camera;
5mod tilemap;
6mod lighting;
7pub mod font;
8
9pub use gpu::GpuContext;
10pub use sprite::{SpriteCommand, SpritePipeline};
11pub use texture::{TextureId, TextureStore};
12pub use camera::Camera2D;
13pub use tilemap::{Tilemap, TilemapStore};
14pub use lighting::{LightingState, LightingUniform, PointLight, LightData, MAX_LIGHTS};
15
16use anyhow::Result;
17
18pub struct Renderer {
20 pub gpu: GpuContext,
21 pub sprites: SpritePipeline,
22 pub textures: TextureStore,
23 pub camera: Camera2D,
24 pub lighting: LightingState,
25 pub frame_commands: Vec<SpriteCommand>,
27 pub scale_factor: f32,
29 pub clear_color: [f32; 4],
31}
32
33impl Renderer {
34 pub fn new(window: std::sync::Arc<winit::window::Window>) -> Result<Self> {
36 let scale_factor = window.scale_factor() as f32;
37 let gpu = GpuContext::new(window)?;
38 let sprites = SpritePipeline::new(&gpu);
39 let textures = TextureStore::new();
40 let logical_w = gpu.config.width as f32 / scale_factor;
42 let logical_h = gpu.config.height as f32 / scale_factor;
43 let camera = Camera2D {
44 viewport_size: [logical_w, logical_h],
45 ..Camera2D::default()
46 };
47 Ok(Self {
48 gpu,
49 sprites,
50 textures,
51 camera,
52 lighting: LightingState::default(),
53 frame_commands: Vec::new(),
54 scale_factor,
55 clear_color: [0.1, 0.1, 0.15, 1.0],
56 })
57 }
58
59 pub fn render_frame(&mut self) -> Result<()> {
61 let output = self.gpu.surface.get_current_texture()?;
62 let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
63
64 let mut encoder = self.gpu.device.create_command_encoder(
65 &wgpu::CommandEncoderDescriptor { label: Some("frame_encoder") },
66 );
67
68 self.frame_commands.sort_by(|a, b| {
70 a.layer.cmp(&b.layer).then(a.texture_id.cmp(&b.texture_id))
71 });
72
73 let lighting_uniform = self.lighting.to_uniform();
74 let clear_color = wgpu::Color {
75 r: self.clear_color[0] as f64,
76 g: self.clear_color[1] as f64,
77 b: self.clear_color[2] as f64,
78 a: self.clear_color[3] as f64,
79 };
80
81 self.sprites.render(
82 &self.gpu,
83 &self.textures,
84 &self.camera,
85 &lighting_uniform,
86 &self.frame_commands,
87 &view,
88 &mut encoder,
89 clear_color,
90 );
91
92 self.gpu.queue.submit(std::iter::once(encoder.finish()));
93 output.present();
94
95 self.frame_commands.clear();
96 Ok(())
97 }
98
99 pub fn resize(&mut self, physical_width: u32, physical_height: u32, scale_factor: f32) {
102 if physical_width > 0 && physical_height > 0 {
103 self.scale_factor = scale_factor;
104 self.gpu.config.width = physical_width;
105 self.gpu.config.height = physical_height;
106 self.gpu.surface.configure(&self.gpu.device, &self.gpu.config);
107 self.camera.viewport_size = [
109 physical_width as f32 / scale_factor,
110 physical_height as f32 / scale_factor,
111 ];
112 }
113 }
114}