pub struct RenderWindow { /* private fields */ }Expand description
A renderable window that combines a winit Window with a WindowContext.
This is the primary type for rendering to a window. It implements
Deref<Target = WindowContext>, so all WindowContext methods are
available directly.
§GPU Profiling
Attach a GpuFrameProfiler via set_gpu_profiler
to automatically profile render passes. Once attached, all frames created via
begin_frame will include GPU profiling.
§Example
let mut render_window = RenderWindow::builder()
.with_depth_default()
.build(window, graphics)
.expect("Failed to create window");
// In render loop:
let frame = render_window.begin_frame().expect("Surface available");
{
let mut pass = frame.render_pass()
.clear_color(Color::BLACK)
.with_window_depth()
.clear_depth(0.0)
.build();
// Render commands...
}
// Frame auto-submits on dropImplementations§
Source§impl RenderWindow
impl RenderWindow
Sourcepub fn builder() -> RenderWindowBuilder
pub fn builder() -> RenderWindowBuilder
Create a new builder for configuring a render window.
Sourcepub fn new(
window: Window,
context: Arc<GraphicsContext>,
) -> Result<Self, GraphicsError>
pub fn new( window: Window, context: Arc<GraphicsContext>, ) -> Result<Self, GraphicsError>
Create a new renderable window with default settings.
Sourcepub fn new_with_depth(
window: Window,
context: Arc<GraphicsContext>,
) -> Result<Self, GraphicsError>
pub fn new_with_depth( window: Window, context: Arc<GraphicsContext>, ) -> Result<Self, GraphicsError>
Create a new renderable window with an auto-resizing depth texture.
This is equivalent to using builder() with with_depth_default().
Sourcepub fn new_with_descriptor(
window: Window,
context: Arc<GraphicsContext>,
descriptor: WindowContextDescriptor,
) -> Result<Self, GraphicsError>
pub fn new_with_descriptor( window: Window, context: Arc<GraphicsContext>, descriptor: WindowContextDescriptor, ) -> Result<Self, GraphicsError>
Create a new renderable window with a descriptor.
Sourcepub fn begin_frame(&mut self) -> Option<Frame<'_>>
pub fn begin_frame(&mut self) -> Option<Frame<'_>>
Begin a new frame for rendering.
Returns Some(Frame) if the surface is available, or None if the
surface is temporarily unavailable (e.g., window minimized).
§Example
if let Some(frame) = window.begin_frame() {
let mut pass = frame.render_pass()
.clear_color(Color::BLACK)
.build();
// Render commands...
}Examples found in repository?
89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("camera_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }More examples
91 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92 if window_id != self.window_id {
93 return;
94 }
95
96 events.dispatch(|event| {
97 if let astrelis_winit::event::Event::WindowResized(size) = event {
98 self.window.resized(*size);
99 astrelis_winit::event::HandleStatus::consumed()
100 } else {
101 astrelis_winit::event::HandleStatus::ignored()
102 }
103 });
104
105 let Some(frame) = self.window.begin_frame() else {
106 return; // Surface not available
107 };
108 {
109 let _pass = frame
110 .render_pass()
111 .clear_color(Color::from_rgb_u8(20, 30, 40))
112 .label("mesh_primitives_pass")
113 .build();
114 }
115 // Frame auto-submits on drop
116 }89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("render_graph_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }86 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
87 // Get the color for this window
88 let Some(&color) = self.window_colors.get(&window_id) else {
89 return;
90 };
91
92 // WindowManager automatically handles:
93 // 1. Window lookup (no manual HashMap.get_mut)
94 // 2. Resize events (automatic)
95 // 3. Event dispatching
96 self.window_manager
97 .render_window(window_id, events, |window, _events| {
98 // No need to manually handle resize events!
99 // WindowManager already did that for us
100
101 // Just render!
102 let Some(frame) = window.begin_frame() else {
103 return; // Surface not available
104 };
105
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(color)
110 .label("window_manager_pass")
111 .build();
112 // Additional rendering would go here
113 }
114 // Frame auto-submits on drop
115 });
116 }105 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
106 if window_id != self.window_id {
107 return;
108 }
109
110 // Handle resize
111 events.dispatch(|event| {
112 if let astrelis_winit::event::Event::WindowResized(size) = event {
113 self.window.resized(*size);
114 astrelis_winit::event::HandleStatus::consumed()
115 } else {
116 astrelis_winit::event::HandleStatus::ignored()
117 }
118 });
119
120 // In a real application, materials would be bound during rendering:
121 // material.bind(&mut render_pass);
122 // draw_mesh(&mesh);
123
124 // Begin frame
125 let Some(frame) = self.window.begin_frame() else {
126 return; // Surface not available
127 };
128
129 {
130 let _pass = frame
131 .render_pass()
132 .clear_color(Color::from_rgb_u8(20, 30, 40))
133 .label("material_system_pass")
134 .build();
135 // Materials would be applied here in actual rendering
136 // This is a conceptual demonstration
137 }
138 // Frame auto-submits on drop
139 }431 fn render(
432 &mut self,
433 _ctx: &mut astrelis_winit::app::AppCtx,
434 window_id: WindowId,
435 events: &mut astrelis_winit::event::EventBatch,
436 ) {
437 let Some(window) = self.windows.get_mut(&window_id) else {
438 return;
439 };
440
441 // Handle resize
442 events.dispatch(|event| {
443 if let astrelis_winit::event::Event::WindowResized(size) = event {
444 window.resized(*size);
445 astrelis_winit::event::HandleStatus::consumed()
446 } else {
447 astrelis_winit::event::HandleStatus::ignored()
448 }
449 });
450
451 let Some(frame) = window.begin_frame() else {
452 return; // Surface not available
453 };
454 {
455 let mut pass = frame
456 .render_pass()
457 .clear_color(Color::rgb(0.1, 0.1, 0.15))
458 .label("sprite_sheet_pass")
459 .build();
460 pass.set_pipeline(&self.pipeline);
461 pass.set_bind_group(0, &self.bind_group, &[]);
462 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
463 pass.draw(0..6, 0..1);
464 }
465 // Frame auto-submits on drop
466 }Sourcepub fn try_begin_frame(&mut self) -> Result<Frame<'_>, GraphicsError>
pub fn try_begin_frame(&mut self) -> Result<Frame<'_>, GraphicsError>
Try to begin a new frame, returning an error on failure.
Unlike begin_frame, this returns the actual error
for debugging or error handling.
Sourcepub fn id(&self) -> WindowId
pub fn id(&self) -> WindowId
Get the window ID.
Examples found in repository?
25fn main() {
26 logging::init();
27
28 run_app(|ctx| {
29 let graphics_ctx =
30 GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
31
32 let mut windows = HashMap::new();
33
34 // Create 3 windows with different colors
35 let colors = [
36 wgpu::Color {
37 r: 0.8,
38 g: 0.2,
39 b: 0.2,
40 a: 1.0,
41 },
42 wgpu::Color {
43 r: 0.2,
44 g: 0.8,
45 b: 0.2,
46 a: 1.0,
47 },
48 wgpu::Color {
49 r: 0.2,
50 g: 0.2,
51 b: 0.8,
52 a: 1.0,
53 },
54 ];
55
56 for (i, color) in colors.iter().enumerate() {
57 let window = ctx
58 .create_window(WindowDescriptor {
59 title: format!("Window {} - Multi-Window Example", i + 1),
60 size: Some(WinitPhysicalSize::new(400.0, 300.0)),
61 ..Default::default()
62 })
63 .expect("Failed to create window");
64
65 let renderable_window = RenderWindowBuilder::new()
66 .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
67 .with_depth_default()
68 .build(window, graphics_ctx.clone())
69 .expect("Failed to create render window");
70
71 let window_id = renderable_window.id();
72 windows.insert(window_id, (renderable_window, *color));
73 }
74
75 Box::new(App { windows })
76 });
77}More examples
36fn main() {
37 logging::init();
38
39 run_app(|ctx| {
40 let graphics_ctx =
41 GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
42
43 let window = ctx
44 .create_window(WindowDescriptor {
45 title: "Performance Benchmark - Render Stress Test".to_string(),
46 size: Some(WinitPhysicalSize::new(1280.0, 720.0)),
47 ..Default::default()
48 })
49 .expect("Failed to create window");
50
51 let window = RenderWindowBuilder::new()
52 .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
53 .with_depth_default()
54 .build(window, graphics_ctx.clone())
55 .expect("Failed to create render window");
56
57 let window_id = window.id();
58
59 println!("\n═══════════════════════════════════════════════════════");
60 println!(" ⚡ PERFORMANCE BENCHMARK - Render Stress Test");
61 println!("═══════════════════════════════════════════════════════");
62 println!(" CONTROLS:");
63 println!(" [Space] Toggle rendering on/off");
64 println!(" [+/-] Increase/decrease object count");
65 println!(" Starting with 1000 objects");
66 println!("═══════════════════════════════════════════════════════\n");
67
68 Box::new(PerformanceBenchmark {
69 _context: graphics_ctx,
70 window,
71 window_id,
72 object_count: 1000,
73 rendering: true,
74 frame_count: 0,
75 last_fps_time: Instant::now(),
76 fps: 0.0,
77 last_frame_time: 0.0,
78 })
79 });
80}30fn main() {
31 logging::init();
32
33 run_app(|ctx| {
34 let graphics_ctx =
35 GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
36
37 let window = ctx
38 .create_window(WindowDescriptor {
39 title: "Camera Demo - View & Projection".to_string(),
40 size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
41 ..Default::default()
42 })
43 .expect("Failed to create window");
44
45 let window = RenderWindowBuilder::new()
46 .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
47 .with_depth_default()
48 .build(window, graphics_ctx.clone())
49 .expect("Failed to create render window");
50
51 let window_id = window.id();
52
53 println!("\n═══════════════════════════════════════════════════════");
54 println!(" 📹 CAMERA DEMO - View & Projection");
55 println!("═══════════════════════════════════════════════════════");
56 println!("\n CAMERA API FEATURES:");
57 println!(" • Orthographic cameras (2D, UI, isometric)");
58 println!(" • Perspective cameras (3D scenes)");
59 println!(" • View matrix (position, rotation, look-at)");
60 println!(" • Projection matrix (FOV, aspect, near/far planes)");
61 println!(" • Screen-to-world coordinate conversion");
62 println!(" • Camera movement helpers");
63 println!("\n CAMERA TYPES:");
64 println!(" • OrthographicCamera - 2D games, UI overlays");
65 println!(" camera.orthographic(left, right, bottom, top, near, far)");
66 println!(" • PerspectiveCamera - 3D scenes");
67 println!(" camera.perspective(fov, aspect, near, far)");
68 println!("\n Camera API Usage:");
69 println!(" let camera = Camera::new()");
70 println!(" .position(Vec3::new(0.0, 5.0, 10.0))");
71 println!(" .look_at(Vec3::ZERO)");
72 println!(" .perspective(60.0, aspect, 0.1, 100.0);");
73 println!(" let view_proj = camera.view_projection_matrix();");
74 println!("═══════════════════════════════════════════════════════\n");
75
76 tracing::info!("Camera demo initialized");
77
78 Box::new(CameraDemo {
79 _context: graphics_ctx,
80 window,
81 window_id,
82 })
83 });
84}29fn main() {
30 logging::init();
31
32 run_app(|ctx| {
33 let graphics_ctx =
34 GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
35
36 let window = ctx
37 .create_window(WindowDescriptor {
38 title: "Render Graph Demo - Multi-Pass Rendering".to_string(),
39 size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
40 ..Default::default()
41 })
42 .expect("Failed to create window");
43
44 let window = RenderWindowBuilder::new()
45 .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
46 .with_depth_default()
47 .build(window, graphics_ctx.clone())
48 .expect("Failed to create render window");
49
50 let window_id = window.id();
51
52 println!("\n═══════════════════════════════════════════════════════");
53 println!(" 🔀 RENDER GRAPH DEMO - Multi-Pass Rendering");
54 println!("═══════════════════════════════════════════════════════");
55 println!("\n RENDER GRAPH FEATURES:");
56 println!(" • Declarative pass definition");
57 println!(" • Automatic dependency resolution");
58 println!(" • Resource lifetime management");
59 println!(" • Parallel pass execution");
60 println!(" • Automatic optimization");
61 println!("\n EXAMPLE PIPELINE:");
62 println!(" 1. Shadow Pass → depth texture");
63 println!(" 2. Geometry Pass → color + normal + depth");
64 println!(" 3. Lighting Pass → lit scene");
65 println!(" 4. Post-Processing → bloom, tone mapping");
66 println!(" 5. UI Pass → final composite");
67 println!("\n Render Graph API Usage:");
68 println!(" let mut graph = RenderGraph::new();");
69 println!(" graph.add_pass(\"shadow\", shadow_pass_descriptor);");
70 println!(" graph.add_pass(\"geometry\", geometry_pass_descriptor);");
71 println!(" graph.add_dependency(\"lighting\", \"geometry\");");
72 println!(" graph.compile();");
73 println!(" graph.execute(&mut encoder);");
74 println!("═══════════════════════════════════════════════════════\n");
75
76 tracing::info!("Render graph demo initialized");
77
78 Box::new(RenderGraphDemo {
79 _context: graphics_ctx,
80 window,
81 window_id,
82 })
83 });
84}29fn main() {
30 logging::init();
31
32 run_app(|ctx| {
33 let graphics_ctx =
34 GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
35
36 let window = ctx
37 .create_window(WindowDescriptor {
38 title: "Mesh Primitives Demo - Geometry API".to_string(),
39 size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
40 ..Default::default()
41 })
42 .expect("Failed to create window");
43
44 let window = RenderWindowBuilder::new()
45 .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
46 .with_depth_default()
47 .build(window, graphics_ctx.clone())
48 .expect("Failed to create render window");
49
50 let window_id = window.id();
51
52 println!("\n═══════════════════════════════════════════════════════");
53 println!(" 📐 MESH PRIMITIVES DEMO - Geometry API");
54 println!("═══════════════════════════════════════════════════════");
55 println!("\n MESH API FEATURES:");
56 println!(" • MeshBuilder for custom geometry");
57 println!(" • Primitive generation (cube, sphere, plane, etc.)");
58 println!(" • Flexible vertex formats (Position, Normal, UV, Color)");
59 println!(" • Index buffer optimization");
60 println!(" • Instanced rendering support");
61 println!("\n EXAMPLE PRIMITIVES:");
62 println!(" • Cube - box with 24 vertices (6 faces × 4 vertices)");
63 println!(" • Sphere - tessellated sphere with UV mapping");
64 println!(" • Plane - quad with optional subdivisions");
65 println!(" • Cylinder - sides + caps");
66 println!(" • Custom - arbitrary vertex/index data");
67 println!("\n Mesh API Usage:");
68 println!(" let mesh = MeshBuilder::new()");
69 println!(" .with_positions(vertices)");
70 println!(" .with_normals(normals)");
71 println!(" .with_uvs(uvs)");
72 println!(" .with_indices(indices)");
73 println!(" .build(&ctx);");
74 println!(" mesh.draw(&mut pass);");
75 println!(" mesh.draw_instanced(&mut pass, instance_count);");
76 println!("═══════════════════════════════════════════════════════\n");
77
78 tracing::info!("Mesh primitives demo initialized");
79
80 Box::new(MeshPrimitivesDemo {
81 _context: graphics_ctx,
82 window,
83 window_id,
84 })
85 });
86}278fn main() {
279 logging::init();
280
281 run_app(|ctx| {
282 let tier_override = parse_tier();
283
284 // Use the capability API to configure GPU requirements.
285 // For auto-detect, request the best capability (graceful degradation).
286 // For a specific tier, require that tier's capability.
287 let descriptor = match tier_override {
288 None => GraphicsContextDescriptor::new().request_capability::<BestBatchCapability2D>(),
289 Some(RenderTier::Direct) => {
290 GraphicsContextDescriptor::new().require_capability::<DirectBatchCapability2D>()
291 }
292 Some(RenderTier::Indirect) => {
293 GraphicsContextDescriptor::new().require_capability::<IndirectBatchCapability2D>()
294 }
295 Some(RenderTier::Bindless) => {
296 GraphicsContextDescriptor::new().require_capability::<BindlessBatchCapability2D>()
297 }
298 };
299 let graphics_ctx =
300 pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
301 .expect("Failed to create graphics context");
302
303 let window = ctx
304 .create_window(WindowDescriptor {
305 title: "Batched Renderer Example".to_string(),
306 size: Some(WinitPhysicalSize::new(800.0, 600.0)),
307 ..Default::default()
308 })
309 .expect("Failed to create window");
310
311 let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
312
313 let renderable_window = RenderWindowBuilder::new()
314 .color_format(surface_format)
315 .with_depth_default()
316 .build(window, graphics_ctx.clone())
317 .expect("Failed to create render window");
318
319 let window_id = renderable_window.id();
320
321 let renderer =
322 create_batch_renderer_2d(graphics_ctx.clone(), surface_format, tier_override);
323
324 tracing::info!("Using render tier: {}", renderer.tier());
325
326 // Create initial depth buffer
327 let depth_texture = graphics_ctx
328 .device()
329 .create_texture(&wgpu::TextureDescriptor {
330 label: Some("example_depth"),
331 size: wgpu::Extent3d {
332 width: 1,
333 height: 1,
334 depth_or_array_layers: 1,
335 },
336 mip_level_count: 1,
337 sample_count: 1,
338 dimension: wgpu::TextureDimension::D2,
339 format: DEPTH_FORMAT,
340 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
341 view_formats: &[],
342 });
343 let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
344
345 let mut windows = HashMap::new();
346 windows.insert(window_id, renderable_window);
347
348 Box::new(App {
349 context: graphics_ctx,
350 windows,
351 renderer,
352 depth_texture,
353 depth_view,
354 depth_width: 1,
355 depth_height: 1,
356 frame_count: 0,
357 })
358 });
359}Sourcepub fn context(&self) -> &WindowContext
pub fn context(&self) -> &WindowContext
Get the window context.
Examples found in repository?
404 fn update(
405 &mut self,
406 _ctx: &mut astrelis_winit::app::AppCtx,
407 _time: &astrelis_winit::FrameTime,
408 ) {
409 let now = Instant::now();
410 let dt = now.duration_since(self.last_update).as_secs_f32();
411 self.last_update = now;
412
413 // Update animation
414 if self.animation.update(dt) {
415 // Frame changed - update vertex buffer with new UVs
416 let frame = self.animation.current_frame();
417 let uv = self.sprite_sheet.sprite_uv(frame);
418 let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
419
420 // Get context from first window
421 if let Some(window) = self.windows.values().next() {
422 window.context().graphics_context().queue().write_buffer(
423 &self.vertex_buffer,
424 0,
425 bytemuck::cast_slice(&vertices),
426 );
427 }
428 }
429 }Sourcepub fn context_mut(&mut self) -> &mut WindowContext
pub fn context_mut(&mut self) -> &mut WindowContext
Get mutable access to the window context.
Sourcepub fn graphics(&self) -> &GraphicsContext
pub fn graphics(&self) -> &GraphicsContext
Get the graphics context.
Sourcepub fn graphics_arc(&self) -> &Arc<GraphicsContext>
pub fn graphics_arc(&self) -> &Arc<GraphicsContext>
Get the Arc-wrapped graphics context.
Sourcepub fn surface_format(&self) -> TextureFormat
pub fn surface_format(&self) -> TextureFormat
Get the surface texture format.
Sourcepub fn resized(&mut self, new_size: LogicalSize<u32>)
pub fn resized(&mut self, new_size: LogicalSize<u32>)
Handle window resize event (logical size).
Examples found in repository?
89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("camera_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }More examples
91 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92 if window_id != self.window_id {
93 return;
94 }
95
96 events.dispatch(|event| {
97 if let astrelis_winit::event::Event::WindowResized(size) = event {
98 self.window.resized(*size);
99 astrelis_winit::event::HandleStatus::consumed()
100 } else {
101 astrelis_winit::event::HandleStatus::ignored()
102 }
103 });
104
105 let Some(frame) = self.window.begin_frame() else {
106 return; // Surface not available
107 };
108 {
109 let _pass = frame
110 .render_pass()
111 .clear_color(Color::from_rgb_u8(20, 30, 40))
112 .label("mesh_primitives_pass")
113 .build();
114 }
115 // Frame auto-submits on drop
116 }89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("render_graph_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }105 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
106 if window_id != self.window_id {
107 return;
108 }
109
110 // Handle resize
111 events.dispatch(|event| {
112 if let astrelis_winit::event::Event::WindowResized(size) = event {
113 self.window.resized(*size);
114 astrelis_winit::event::HandleStatus::consumed()
115 } else {
116 astrelis_winit::event::HandleStatus::ignored()
117 }
118 });
119
120 // In a real application, materials would be bound during rendering:
121 // material.bind(&mut render_pass);
122 // draw_mesh(&mesh);
123
124 // Begin frame
125 let Some(frame) = self.window.begin_frame() else {
126 return; // Surface not available
127 };
128
129 {
130 let _pass = frame
131 .render_pass()
132 .clear_color(Color::from_rgb_u8(20, 30, 40))
133 .label("material_system_pass")
134 .build();
135 // Materials would be applied here in actual rendering
136 // This is a conceptual demonstration
137 }
138 // Frame auto-submits on drop
139 }431 fn render(
432 &mut self,
433 _ctx: &mut astrelis_winit::app::AppCtx,
434 window_id: WindowId,
435 events: &mut astrelis_winit::event::EventBatch,
436 ) {
437 let Some(window) = self.windows.get_mut(&window_id) else {
438 return;
439 };
440
441 // Handle resize
442 events.dispatch(|event| {
443 if let astrelis_winit::event::Event::WindowResized(size) = event {
444 window.resized(*size);
445 astrelis_winit::event::HandleStatus::consumed()
446 } else {
447 astrelis_winit::event::HandleStatus::ignored()
448 }
449 });
450
451 let Some(frame) = window.begin_frame() else {
452 return; // Surface not available
453 };
454 {
455 let mut pass = frame
456 .render_pass()
457 .clear_color(Color::rgb(0.1, 0.1, 0.15))
458 .label("sprite_sheet_pass")
459 .build();
460 pass.set_pipeline(&self.pipeline);
461 pass.set_bind_group(0, &self.bind_group, &[]);
462 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
463 pass.draw(0..6, 0..1);
464 }
465 // Frame auto-submits on drop
466 }486 fn render(
487 &mut self,
488 _ctx: &mut astrelis_winit::app::AppCtx,
489 window_id: WindowId,
490 events: &mut astrelis_winit::event::EventBatch,
491 ) {
492 let Some(window) = self.windows.get_mut(&window_id) else {
493 return;
494 };
495
496 // Handle resize
497 events.dispatch(|event| {
498 if let astrelis_winit::event::Event::WindowResized(size) = event {
499 window.resized(*size);
500 astrelis_winit::event::HandleStatus::consumed()
501 } else {
502 astrelis_winit::event::HandleStatus::ignored()
503 }
504 });
505
506 let Some(frame) = window.begin_frame() else {
507 return; // Surface not available
508 };
509
510 {
511 let mut pass = frame
512 .render_pass()
513 .clear_color(Color::rgb(0.05, 0.05, 0.08))
514 .label("image_blitting_pass")
515 .build();
516 pass.set_pipeline(&self.pipeline);
517 pass.set_bind_group(0, &self.bind_group, &[]);
518 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
519 pass.draw(0..6, 0..1);
520 }
521 // Frame auto-submits on drop
522 }Sourcepub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)
pub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)
Handle window resize event (physical size).
Sourcepub fn physical_size(&self) -> PhysicalSize<u32>
pub fn physical_size(&self) -> PhysicalSize<u32>
Get the physical size of the window.
Examples found in repository?
370 fn render(
371 &mut self,
372 _ctx: &mut astrelis_winit::app::AppCtx,
373 window_id: WindowId,
374 events: &mut astrelis_winit::event::EventBatch,
375 ) {
376 // Handle resize and get dimensions (scoped to release window borrow)
377 let (phys_width, phys_height) = {
378 let Some(window) = self.windows.get_mut(&window_id) else {
379 return;
380 };
381
382 events.dispatch(|event| {
383 if let astrelis_winit::event::Event::WindowResized(size) = event {
384 window.resized(*size);
385 astrelis_winit::event::HandleStatus::consumed()
386 } else {
387 astrelis_winit::event::HandleStatus::ignored()
388 }
389 });
390
391 let phys = window.physical_size();
392 (phys.width, phys.height)
393 };
394
395 let width = phys_width as f32;
396 let height = phys_height as f32;
397
398 if width < 1.0 || height < 1.0 {
399 return;
400 }
401
402 // Ensure depth buffer matches viewport
403 self.ensure_depth_buffer(phys_width, phys_height);
404
405 // Build instances and prepare GPU data
406 let instances = self.build_instances(width, height);
407 let batch = DrawBatch2D {
408 instances,
409 textures: vec![],
410 projection: Self::ortho_projection(width, height),
411 };
412 self.renderer.prepare(&batch);
413
414 let stats = self.renderer.stats();
415 if self.frame_count.is_multiple_of(120) {
416 tracing::info!(
417 "Frame {}: {} instances ({} opaque, {} transparent), {} draw calls",
418 self.frame_count,
419 stats.instance_count,
420 stats.opaque_count,
421 stats.transparent_count,
422 stats.draw_calls,
423 );
424 }
425
426 // Re-borrow window for rendering
427 let window = self.windows.get_mut(&window_id).unwrap();
428 let Some(frame) = window.begin_frame() else {
429 return; // Surface not available
430 };
431
432 // Create render pass with depth stencil attachment
433 {
434 let mut pass = frame
435 .render_pass()
436 .clear_color(Color::rgba(0.08, 0.08, 0.1, 1.0))
437 .depth_attachment(&self.depth_view)
438 .clear_depth(0.0) // 0.0 = far with GreaterEqual
439 .label("batched_example_pass")
440 .build();
441 self.renderer.render(pass.wgpu_pass());
442 }
443 // Frame auto-submits on drop
444 }Sourcepub fn scale_factor(&self) -> ScaleFactor
pub fn scale_factor(&self) -> ScaleFactor
Get the scale factor.
Sourcepub fn set_gpu_profiler(&mut self, profiler: Arc<GpuFrameProfiler>)
pub fn set_gpu_profiler(&mut self, profiler: Arc<GpuFrameProfiler>)
Attach a GPU profiler to this window.
Sourcepub fn remove_gpu_profiler(&mut self) -> Option<Arc<GpuFrameProfiler>>
pub fn remove_gpu_profiler(&mut self) -> Option<Arc<GpuFrameProfiler>>
Remove the GPU profiler from this window.
Sourcepub fn gpu_profiler(&self) -> Option<&Arc<GpuFrameProfiler>>
pub fn gpu_profiler(&self) -> Option<&Arc<GpuFrameProfiler>>
Get a reference to the GPU profiler, if attached.
Sourcepub fn depth_view(&self) -> Option<Arc<TextureView>>
pub fn depth_view(&self) -> Option<Arc<TextureView>>
Get the depth texture view if available (Arc-wrapped).
Sourcepub fn depth_view_ref(&self) -> Option<&TextureView>
pub fn depth_view_ref(&self) -> Option<&TextureView>
Get a reference to the depth texture view (without Arc).
Sourcepub fn depth_format(&self) -> Option<TextureFormat>
pub fn depth_format(&self) -> Option<TextureFormat>
Get the depth texture format, if depth is enabled.
Returns the format used for the depth texture, or None if depth is not enabled. Use this to configure renderers that need to match the depth format.
Sourcepub fn ensure_depth(&mut self, format: TextureFormat)
pub fn ensure_depth(&mut self, format: TextureFormat)
Ensure a depth texture exists for this window.
Methods from Deref<Target = WindowContext>§
Sourcepub fn resized(&mut self, new_size: LogicalSize<u32>)
pub fn resized(&mut self, new_size: LogicalSize<u32>)
Handle window resize event (logical size).
Sourcepub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)
pub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)
Handle window resize event (physical size).
pub fn window(&self) -> &Window
Sourcepub fn graphics_context(&self) -> &GraphicsContext
pub fn graphics_context(&self) -> &GraphicsContext
Examples found in repository?
404 fn update(
405 &mut self,
406 _ctx: &mut astrelis_winit::app::AppCtx,
407 _time: &astrelis_winit::FrameTime,
408 ) {
409 let now = Instant::now();
410 let dt = now.duration_since(self.last_update).as_secs_f32();
411 self.last_update = now;
412
413 // Update animation
414 if self.animation.update(dt) {
415 // Frame changed - update vertex buffer with new UVs
416 let frame = self.animation.current_frame();
417 let uv = self.sprite_sheet.sprite_uv(frame);
418 let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
419
420 // Get context from first window
421 if let Some(window) = self.windows.values().next() {
422 window.context().graphics_context().queue().write_buffer(
423 &self.vertex_buffer,
424 0,
425 bytemuck::cast_slice(&vertices),
426 );
427 }
428 }
429 }pub fn surface(&self) -> &Surface<'static>
pub fn surface_config(&self) -> &SurfaceConfiguration
Sourcepub fn surface_format(&self) -> TextureFormat
pub fn surface_format(&self) -> TextureFormat
Get the surface texture format.
This is the format that render pipelines must use when rendering to this
window’s surface. Pass this to renderer constructors like
LineRenderer::new.
Sourcepub fn logical_size(&self) -> LogicalSize<u32>
pub fn logical_size(&self) -> LogicalSize<u32>
Get the logical size of the window.
Sourcepub fn physical_size(&self) -> PhysicalSize<u32>
pub fn physical_size(&self) -> PhysicalSize<u32>
Get the physical size of the window.
Sourcepub fn logical_size_f32(&self) -> LogicalSize<f32>
pub fn logical_size_f32(&self) -> LogicalSize<f32>
Get the logical size as f32.
Sourcepub fn physical_size_f32(&self) -> PhysicalSize<f32>
pub fn physical_size_f32(&self) -> PhysicalSize<f32>
Get the physical size as f32.
Sourcepub fn reconfigure_surface(&mut self, config: SurfaceConfiguration)
pub fn reconfigure_surface(&mut self, config: SurfaceConfiguration)
Reconfigure the surface with a new configuration.
Sourcepub fn depth_view(&self) -> Option<Arc<TextureView>>
pub fn depth_view(&self) -> Option<Arc<TextureView>>
Get the depth texture view if available.
Returns an Arc-wrapped view for cheap, lifetime-free sharing.
Sourcepub fn depth_format(&self) -> Option<TextureFormat>
pub fn depth_format(&self) -> Option<TextureFormat>
Get the depth texture format, if depth is enabled.
Returns the format used for the depth texture, or None if depth is not enabled. Use this to configure renderers that need to match the depth format.
Sourcepub fn ensure_depth(&mut self, format: TextureFormat)
pub fn ensure_depth(&mut self, format: TextureFormat)
Ensure a depth texture exists for this window.
If no depth texture exists, creates one with the given format. If a depth texture already exists, this is a no-op.
Trait Implementations§
Source§impl Deref for RenderWindow
impl Deref for RenderWindow
Source§impl DerefMut for RenderWindow
impl DerefMut for RenderWindow
Source§impl WindowBackend for RenderWindow
impl WindowBackend for RenderWindow
type FrameContext = Frame<'static>
type Error = GraphicsError
Source§fn try_begin_drawing(&mut self) -> Result<Self::FrameContext, Self::Error>
fn try_begin_drawing(&mut self) -> Result<Self::FrameContext, Self::Error>
Source§fn begin_drawing(&mut self) -> Self::FrameContext
fn begin_drawing(&mut self) -> Self::FrameContext
Auto Trait Implementations§
impl !Freeze for RenderWindow
impl !RefUnwindSafe for RenderWindow
impl Send for RenderWindow
impl Sync for RenderWindow
impl Unpin for RenderWindow
impl UnsafeUnpin for RenderWindow
impl !UnwindSafe for RenderWindow
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more