pub struct RenderableWindow { /* private fields */ }Expand description
A renderable window that combines a window with a rendering context.
Implementations§
Source§impl RenderableWindow
impl RenderableWindow
pub fn new(window: Window, context: &'static GraphicsContext) -> Self
Sourcepub fn new_with_descriptor(
window: Window,
context: &'static GraphicsContext,
descriptor: WindowContextDescriptor,
) -> Self
pub fn new_with_descriptor( window: Window, context: &'static GraphicsContext, descriptor: WindowContextDescriptor, ) -> Self
Examples found in repository?
examples/multi_window.rs (lines 67-74)
28fn main() {
29 logging::init();
30
31 run_app(|ctx| {
32 let graphics_ctx = GraphicsContext::new_sync();
33
34 let mut windows = HashMap::new();
35
36 // Create 3 windows with different colors
37 let colors = [
38 wgpu::Color {
39 r: 0.8,
40 g: 0.2,
41 b: 0.2,
42 a: 1.0,
43 },
44 wgpu::Color {
45 r: 0.2,
46 g: 0.8,
47 b: 0.2,
48 a: 1.0,
49 },
50 wgpu::Color {
51 r: 0.2,
52 g: 0.2,
53 b: 0.8,
54 a: 1.0,
55 },
56 ];
57
58 for (i, color) in colors.iter().enumerate() {
59 let window = ctx
60 .create_window(WindowDescriptor {
61 title: format!("Window {} - Multi-Window Example", i + 1),
62 size: Some(PhysicalSize::new(400.0, 300.0)),
63 ..Default::default()
64 })
65 .expect("Failed to create window");
66
67 let renderable_window = RenderableWindow::new_with_descriptor(
68 window,
69 graphics_ctx,
70 WindowContextDescriptor {
71 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
72 ..Default::default()
73 },
74 );
75
76 let window_id = renderable_window.id();
77 windows.insert(window_id, (renderable_window, *color));
78 }
79
80 Box::new(App {
81 context: graphics_ctx,
82 windows,
83 })
84 });
85}More examples
examples/sprite_sheet.rs (lines 164-171)
148fn main() {
149 logging::init();
150
151 run_app(|ctx| {
152 let graphics_ctx = GraphicsContext::new_sync();
153 let mut windows = HashMap::new();
154
155 let scale = Window::platform_dpi() as f32;
156 let window = ctx
157 .create_window(WindowDescriptor {
158 title: "Sprite Sheet Animation Example".to_string(),
159 size: Some(PhysicalSize::new(400.0 * scale, 400.0 * scale)),
160 ..Default::default()
161 })
162 .expect("Failed to create window");
163
164 let renderable_window = RenderableWindow::new_with_descriptor(
165 window,
166 graphics_ctx,
167 WindowContextDescriptor {
168 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
169 ..Default::default()
170 },
171 );
172
173 let window_id = renderable_window.id();
174 windows.insert(window_id, renderable_window);
175
176 // Generate sprite sheet
177 let (sprite_data, tex_width, tex_height) = generate_sprite_sheet_data();
178 let sprite_sheet = SpriteSheet::from_data(
179 graphics_ctx,
180 &sprite_data,
181 tex_width,
182 tex_height,
183 SpriteSheetDescriptor {
184 sprite_width: 64,
185 sprite_height: 64,
186 columns: 4,
187 rows: 1,
188 ..Default::default()
189 },
190 );
191
192 // Create animation (4 frames at 8 fps)
193 let animation = SpriteAnimation::new(4, 8.0);
194
195 // Create shader module
196 let shader = graphics_ctx.device.create_shader_module(wgpu::ShaderModuleDescriptor {
197 label: Some("Sprite Shader"),
198 source: wgpu::ShaderSource::Wgsl(SHADER.into()),
199 });
200
201 // Create bind group layout
202 let bind_group_layout = graphics_ctx.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
203 label: Some("Sprite Bind Group Layout"),
204 entries: &[
205 wgpu::BindGroupLayoutEntry {
206 binding: 0,
207 visibility: wgpu::ShaderStages::VERTEX,
208 ty: wgpu::BindingType::Buffer {
209 ty: wgpu::BufferBindingType::Uniform,
210 has_dynamic_offset: false,
211 min_binding_size: None,
212 },
213 count: None,
214 },
215 wgpu::BindGroupLayoutEntry {
216 binding: 1,
217 visibility: wgpu::ShaderStages::FRAGMENT,
218 ty: wgpu::BindingType::Texture {
219 sample_type: wgpu::TextureSampleType::Float { filterable: true },
220 view_dimension: wgpu::TextureViewDimension::D2,
221 multisampled: false,
222 },
223 count: None,
224 },
225 wgpu::BindGroupLayoutEntry {
226 binding: 2,
227 visibility: wgpu::ShaderStages::FRAGMENT,
228 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
229 count: None,
230 },
231 ],
232 });
233
234 // Create pipeline layout
235 let pipeline_layout = graphics_ctx.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
236 label: Some("Sprite Pipeline Layout"),
237 bind_group_layouts: &[&bind_group_layout],
238 push_constant_ranges: &[],
239 });
240
241 // Create render pipeline
242 let pipeline = graphics_ctx.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
243 label: Some("Sprite Pipeline"),
244 layout: Some(&pipeline_layout),
245 vertex: wgpu::VertexState {
246 module: &shader,
247 entry_point: Some("vs_main"),
248 buffers: &[wgpu::VertexBufferLayout {
249 array_stride: std::mem::size_of::<Vertex>() as u64,
250 step_mode: wgpu::VertexStepMode::Vertex,
251 attributes: &[
252 wgpu::VertexAttribute {
253 offset: 0,
254 shader_location: 0,
255 format: wgpu::VertexFormat::Float32x2,
256 },
257 wgpu::VertexAttribute {
258 offset: 8,
259 shader_location: 1,
260 format: wgpu::VertexFormat::Float32x2,
261 },
262 ],
263 }],
264 compilation_options: wgpu::PipelineCompilationOptions::default(),
265 },
266 fragment: Some(wgpu::FragmentState {
267 module: &shader,
268 entry_point: Some("fs_main"),
269 targets: &[Some(wgpu::ColorTargetState {
270 format: wgpu::TextureFormat::Bgra8UnormSrgb,
271 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
272 write_mask: wgpu::ColorWrites::ALL,
273 })],
274 compilation_options: wgpu::PipelineCompilationOptions::default(),
275 }),
276 primitive: wgpu::PrimitiveState {
277 topology: wgpu::PrimitiveTopology::TriangleList,
278 ..Default::default()
279 },
280 depth_stencil: None,
281 multisample: wgpu::MultisampleState::default(),
282 multiview: None,
283 cache: None,
284 });
285
286 // Create uniform buffer
287 let uniforms = Uniforms {
288 mvp: [
289 [1.0, 0.0, 0.0, 0.0],
290 [0.0, 1.0, 0.0, 0.0],
291 [0.0, 0.0, 1.0, 0.0],
292 [0.0, 0.0, 0.0, 1.0],
293 ],
294 };
295 let uniform_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
296 label: Some("Uniform Buffer"),
297 contents: bytemuck::cast_slice(&[uniforms]),
298 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
299 });
300
301 // Create sampler
302 let sampler = graphics_ctx.device.create_sampler(&wgpu::SamplerDescriptor {
303 label: Some("Sprite Sampler"),
304 mag_filter: wgpu::FilterMode::Linear,
305 min_filter: wgpu::FilterMode::Linear,
306 ..Default::default()
307 });
308
309 // Create bind group
310 let bind_group = graphics_ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
311 label: Some("Sprite Bind Group"),
312 layout: &bind_group_layout,
313 entries: &[
314 wgpu::BindGroupEntry {
315 binding: 0,
316 resource: uniform_buffer.as_entire_binding(),
317 },
318 wgpu::BindGroupEntry {
319 binding: 1,
320 resource: wgpu::BindingResource::TextureView(sprite_sheet.view()),
321 },
322 wgpu::BindGroupEntry {
323 binding: 2,
324 resource: wgpu::BindingResource::Sampler(&sampler),
325 },
326 ],
327 });
328
329 // Initial vertex buffer (will be updated each frame with new UVs)
330 let vertices = create_quad_vertices(0.0, 0.0, 1.0, 1.0);
331 let vertex_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
332 label: Some("Vertex Buffer"),
333 contents: bytemuck::cast_slice(&vertices),
334 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
335 });
336
337 Box::new(App {
338 _context: graphics_ctx,
339 windows,
340 pipeline,
341 bind_group,
342 vertex_buffer,
343 uniform_buffer,
344 sprite_sheet,
345 animation,
346 last_update: Instant::now(),
347 })
348 });
349}examples/textured_window.rs (lines 32-39)
19fn main() {
20 logging::init();
21
22 run_app(|ctx| {
23 let graphics_ctx = GraphicsContext::new_sync();
24
25 let window = ctx
26 .create_window(WindowDescriptor {
27 title: "Textured Window".to_string(),
28 ..Default::default()
29 })
30 .expect("Failed to create window");
31
32 let window = RenderableWindow::new_with_descriptor(
33 window,
34 graphics_ctx,
35 WindowContextDescriptor {
36 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
37 ..Default::default()
38 },
39 );
40
41 let shader = graphics_ctx
42 .device
43 .create_shader_module(wgpu::ShaderModuleDescriptor {
44 label: Some("Texture Shader"),
45 source: wgpu::ShaderSource::Wgsl(include_str!("textured_window.wgsl").into()),
46 });
47
48 let texture_size = wgpu::Extent3d {
49 width: 256,
50 height: 256,
51 depth_or_array_layers: 1,
52 };
53
54 let texture = graphics_ctx
55 .device
56 .create_texture(&wgpu::TextureDescriptor {
57 label: Some("Example Texture"),
58 size: texture_size,
59 mip_level_count: 1,
60 sample_count: 1,
61 dimension: wgpu::TextureDimension::D2,
62 format: wgpu::TextureFormat::Rgba8UnormSrgb,
63 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
64 view_formats: &[],
65 });
66
67 let mut texture_data = vec![0u8; (256 * 256 * 4) as usize];
68 for y in 0..256 {
69 for x in 0..256 {
70 let idx = ((y * 256 + x) * 4) as usize;
71 texture_data[idx] = x as u8;
72 texture_data[idx + 1] = y as u8;
73 texture_data[idx + 2] = ((x + y) / 2) as u8;
74 texture_data[idx + 3] = 255;
75 }
76 }
77
78 graphics_ctx.queue.write_texture(
79 wgpu::TexelCopyTextureInfo {
80 texture: &texture,
81 mip_level: 0,
82 origin: wgpu::Origin3d::ZERO,
83 aspect: wgpu::TextureAspect::All,
84 },
85 &texture_data,
86 wgpu::TexelCopyBufferLayout {
87 offset: 0,
88 bytes_per_row: Some(256 * 4),
89 rows_per_image: Some(256),
90 },
91 texture_size,
92 );
93
94 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
95 let sampler = graphics_ctx
96 .device
97 .create_sampler(&wgpu::SamplerDescriptor {
98 address_mode_u: wgpu::AddressMode::ClampToEdge,
99 address_mode_v: wgpu::AddressMode::ClampToEdge,
100 address_mode_w: wgpu::AddressMode::ClampToEdge,
101 mag_filter: wgpu::FilterMode::Linear,
102 min_filter: wgpu::FilterMode::Nearest,
103 mipmap_filter: wgpu::FilterMode::Nearest,
104 ..Default::default()
105 });
106
107 let bind_group_layout =
108 graphics_ctx
109 .device
110 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
111 label: Some("Texture Bind Group Layout"),
112 entries: &[
113 wgpu::BindGroupLayoutEntry {
114 binding: 0,
115 visibility: wgpu::ShaderStages::FRAGMENT,
116 ty: wgpu::BindingType::Texture {
117 multisampled: false,
118 view_dimension: wgpu::TextureViewDimension::D2,
119 sample_type: wgpu::TextureSampleType::Float { filterable: true },
120 },
121 count: None,
122 },
123 wgpu::BindGroupLayoutEntry {
124 binding: 1,
125 visibility: wgpu::ShaderStages::FRAGMENT,
126 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
127 count: None,
128 },
129 ],
130 });
131
132 let bind_group = graphics_ctx
133 .device
134 .create_bind_group(&wgpu::BindGroupDescriptor {
135 label: Some("Texture Bind Group"),
136 layout: &bind_group_layout,
137 entries: &[
138 wgpu::BindGroupEntry {
139 binding: 0,
140 resource: wgpu::BindingResource::TextureView(&texture_view),
141 },
142 wgpu::BindGroupEntry {
143 binding: 1,
144 resource: wgpu::BindingResource::Sampler(&sampler),
145 },
146 ],
147 });
148
149 let pipeline_layout =
150 graphics_ctx
151 .device
152 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
153 label: Some("Render Pipeline Layout"),
154 bind_group_layouts: &[&bind_group_layout],
155 push_constant_ranges: &[],
156 });
157
158 let pipeline =
159 graphics_ctx
160 .device
161 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
162 label: Some("Render Pipeline"),
163 layout: Some(&pipeline_layout),
164 vertex: wgpu::VertexState {
165 module: &shader,
166 entry_point: Some("vs_main"),
167 buffers: &[wgpu::VertexBufferLayout {
168 array_stride: 4 * 4,
169 step_mode: wgpu::VertexStepMode::Vertex,
170 attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
171 }],
172 compilation_options: wgpu::PipelineCompilationOptions::default(),
173 },
174 fragment: Some(wgpu::FragmentState {
175 module: &shader,
176 entry_point: Some("fs_main"),
177 targets: &[Some(wgpu::ColorTargetState {
178 format: wgpu::TextureFormat::Bgra8UnormSrgb,
179 blend: Some(wgpu::BlendState::REPLACE),
180 write_mask: wgpu::ColorWrites::ALL,
181 })],
182 compilation_options: wgpu::PipelineCompilationOptions::default(),
183 }),
184 primitive: wgpu::PrimitiveState {
185 topology: wgpu::PrimitiveTopology::TriangleList,
186 strip_index_format: None,
187 front_face: wgpu::FrontFace::Ccw,
188 cull_mode: Some(wgpu::Face::Back),
189 polygon_mode: wgpu::PolygonMode::Fill,
190 unclipped_depth: false,
191 conservative: false,
192 },
193 depth_stencil: None,
194 multisample: wgpu::MultisampleState {
195 count: 1,
196 mask: !0,
197 alpha_to_coverage_enabled: false,
198 },
199 multiview: None,
200 cache: None,
201 });
202
203 #[rustfmt::skip]
204 let vertices: &[f32] = &[
205 -0.8, -0.8, 0.0, 1.0,
206 0.8, -0.8, 1.0, 1.0,
207 0.8, 0.8, 1.0, 0.0,
208 -0.8, -0.8, 0.0, 1.0,
209 0.8, 0.8, 1.0, 0.0,
210 -0.8, 0.8, 0.0, 0.0,
211 ];
212
213 let vertex_buffer = graphics_ctx.device.create_buffer(&wgpu::BufferDescriptor {
214 label: Some("Vertex Buffer"),
215 size: (vertices.len() * std::mem::size_of::<f32>()) as u64,
216 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
217 mapped_at_creation: false,
218 });
219
220 graphics_ctx
221 .queue
222 .write_buffer(&vertex_buffer, 0, bytemuck::cast_slice(vertices));
223
224 let window_id = window.id();
225
226 Box::new(App {
227 window,
228 window_id,
229 pipeline,
230 bind_group,
231 vertex_buffer,
232 })
233 });
234}examples/image_blitting.rs (lines 183-190)
167fn main() {
168 logging::init();
169
170 run_app(|ctx| {
171 let graphics_ctx = GraphicsContext::new_sync();
172 let mut windows = HashMap::new();
173
174 let scale = Window::platform_dpi() as f32;
175 let window = ctx
176 .create_window(WindowDescriptor {
177 title: "Image Blitting Example".to_string(),
178 size: Some(PhysicalSize::new(800.0 * scale, 600.0 * scale)),
179 ..Default::default()
180 })
181 .expect("Failed to create window");
182
183 let renderable_window = RenderableWindow::new_with_descriptor(
184 window,
185 graphics_ctx,
186 WindowContextDescriptor {
187 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
188 ..Default::default()
189 },
190 );
191
192 let window_id = renderable_window.id();
193 windows.insert(window_id, renderable_window);
194
195 // Create shader module
196 let shader = graphics_ctx.device.create_shader_module(wgpu::ShaderModuleDescriptor {
197 label: Some("Blit Shader"),
198 source: wgpu::ShaderSource::Wgsl(SHADER.into()),
199 });
200
201 // Create bind group layout
202 let bind_group_layout = graphics_ctx.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
203 label: Some("Blit Bind Group Layout"),
204 entries: &[
205 wgpu::BindGroupLayoutEntry {
206 binding: 0,
207 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
208 ty: wgpu::BindingType::Buffer {
209 ty: wgpu::BufferBindingType::Uniform,
210 has_dynamic_offset: false,
211 min_binding_size: None,
212 },
213 count: None,
214 },
215 wgpu::BindGroupLayoutEntry {
216 binding: 1,
217 visibility: wgpu::ShaderStages::FRAGMENT,
218 ty: wgpu::BindingType::Texture {
219 sample_type: wgpu::TextureSampleType::Float { filterable: true },
220 view_dimension: wgpu::TextureViewDimension::D2,
221 multisampled: false,
222 },
223 count: None,
224 },
225 wgpu::BindGroupLayoutEntry {
226 binding: 2,
227 visibility: wgpu::ShaderStages::FRAGMENT,
228 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
229 count: None,
230 },
231 ],
232 });
233
234 // Create pipeline layout
235 let pipeline_layout = graphics_ctx.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
236 label: Some("Blit Pipeline Layout"),
237 bind_group_layouts: &[&bind_group_layout],
238 push_constant_ranges: &[],
239 });
240
241 // Create render pipeline
242 let pipeline = graphics_ctx.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
243 label: Some("Blit Pipeline"),
244 layout: Some(&pipeline_layout),
245 vertex: wgpu::VertexState {
246 module: &shader,
247 entry_point: Some("vs_main"),
248 buffers: &[wgpu::VertexBufferLayout {
249 array_stride: std::mem::size_of::<Vertex>() as u64,
250 step_mode: wgpu::VertexStepMode::Vertex,
251 attributes: &[
252 wgpu::VertexAttribute {
253 offset: 0,
254 shader_location: 0,
255 format: wgpu::VertexFormat::Float32x2,
256 },
257 wgpu::VertexAttribute {
258 offset: 8,
259 shader_location: 1,
260 format: wgpu::VertexFormat::Float32x2,
261 },
262 ],
263 }],
264 compilation_options: wgpu::PipelineCompilationOptions::default(),
265 },
266 fragment: Some(wgpu::FragmentState {
267 module: &shader,
268 entry_point: Some("fs_main"),
269 targets: &[Some(wgpu::ColorTargetState {
270 format: wgpu::TextureFormat::Bgra8UnormSrgb,
271 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
272 write_mask: wgpu::ColorWrites::ALL,
273 })],
274 compilation_options: wgpu::PipelineCompilationOptions::default(),
275 }),
276 primitive: wgpu::PrimitiveState {
277 topology: wgpu::PrimitiveTopology::TriangleList,
278 strip_index_format: None,
279 front_face: wgpu::FrontFace::Ccw,
280 cull_mode: None,
281 polygon_mode: wgpu::PolygonMode::Fill,
282 unclipped_depth: false,
283 conservative: false,
284 },
285 depth_stencil: None,
286 multisample: wgpu::MultisampleState::default(),
287 multiview: None,
288 cache: None,
289 });
290
291 // Create vertex buffer for a fullscreen quad
292 let vertices = [
293 Vertex { position: [-0.8, -0.8], uv: [0.0, 1.0] },
294 Vertex { position: [0.8, -0.8], uv: [1.0, 1.0] },
295 Vertex { position: [0.8, 0.8], uv: [1.0, 0.0] },
296 Vertex { position: [-0.8, -0.8], uv: [0.0, 1.0] },
297 Vertex { position: [0.8, 0.8], uv: [1.0, 0.0] },
298 Vertex { position: [-0.8, 0.8], uv: [0.0, 0.0] },
299 ];
300 let vertex_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
301 label: Some("Vertex Buffer"),
302 contents: bytemuck::cast_slice(&vertices),
303 usage: wgpu::BufferUsages::VERTEX,
304 });
305
306 // Create uniform buffer
307 let uniforms = Uniforms {
308 mvp: [
309 [1.0, 0.0, 0.0, 0.0],
310 [0.0, 1.0, 0.0, 0.0],
311 [0.0, 0.0, 1.0, 0.0],
312 [0.0, 0.0, 0.0, 1.0],
313 ],
314 tint: [1.0, 1.0, 1.0, 1.0],
315 };
316 let uniform_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
317 label: Some("Uniform Buffer"),
318 contents: bytemuck::cast_slice(&[uniforms]),
319 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
320 });
321
322 // Create CPU-side image buffer
323 let mut image_buffer = ImageBuffer::new(256, 256);
324 image_buffer.clear(30, 30, 40, 255);
325
326 // Create GPU texture
327 let texture = graphics_ctx.device.create_texture(&wgpu::TextureDescriptor {
328 label: Some("Blit Texture"),
329 size: wgpu::Extent3d {
330 width: 256,
331 height: 256,
332 depth_or_array_layers: 1,
333 },
334 mip_level_count: 1,
335 sample_count: 1,
336 dimension: wgpu::TextureDimension::D2,
337 format: wgpu::TextureFormat::Rgba8UnormSrgb,
338 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
339 view_formats: &[],
340 });
341
342 // Create texture view and sampler
343 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
344 let sampler = graphics_ctx.device.create_sampler(&wgpu::SamplerDescriptor {
345 label: Some("Blit Sampler"),
346 address_mode_u: wgpu::AddressMode::ClampToEdge,
347 address_mode_v: wgpu::AddressMode::ClampToEdge,
348 address_mode_w: wgpu::AddressMode::ClampToEdge,
349 mag_filter: wgpu::FilterMode::Nearest, // Pixel-perfect rendering
350 min_filter: wgpu::FilterMode::Nearest,
351 mipmap_filter: wgpu::FilterMode::Nearest,
352 ..Default::default()
353 });
354
355 // Create bind group
356 let bind_group = graphics_ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
357 label: Some("Blit Bind Group"),
358 layout: &bind_group_layout,
359 entries: &[
360 wgpu::BindGroupEntry {
361 binding: 0,
362 resource: uniform_buffer.as_entire_binding(),
363 },
364 wgpu::BindGroupEntry {
365 binding: 1,
366 resource: wgpu::BindingResource::TextureView(&texture_view),
367 },
368 wgpu::BindGroupEntry {
369 binding: 2,
370 resource: wgpu::BindingResource::Sampler(&sampler),
371 },
372 ],
373 });
374
375 Box::new(App {
376 context: graphics_ctx,
377 windows,
378 pipeline,
379 bind_group_layout,
380 vertex_buffer,
381 texture,
382 bind_group,
383 uniform_buffer,
384 image_buffer,
385 start_time: Instant::now(),
386 })
387 });
388}examples/renderer_api.rs (lines 43-50)
28fn main() {
29 logging::init();
30
31 run_app(|ctx| {
32 let graphics_ctx = GraphicsContext::new_sync();
33 let renderer = Renderer::new(graphics_ctx);
34
35 let window = ctx
36 .create_window(WindowDescriptor {
37 title: "Renderer API Example".to_string(),
38 size: Some(PhysicalSize::new(800.0, 600.0)),
39 ..Default::default()
40 })
41 .expect("Failed to create window");
42
43 let window = RenderableWindow::new_with_descriptor(
44 window,
45 graphics_ctx,
46 WindowContextDescriptor {
47 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48 ..Default::default()
49 },
50 );
51
52 let window_id = window.id();
53
54 // Create shader using Renderer API
55 let shader = renderer.create_shader(Some("Color Shader"), SHADER_SOURCE);
56
57 // Create texture using Renderer helper
58 let texture_data = create_gradient_texture();
59 let texture = renderer.create_texture_2d(
60 Some("Gradient Texture"),
61 256,
62 256,
63 wgpu::TextureFormat::Rgba8UnormSrgb,
64 wgpu::TextureUsages::TEXTURE_BINDING,
65 &texture_data,
66 );
67
68 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
69 let sampler = renderer.create_linear_sampler(Some("Linear Sampler"));
70
71 // Create bind group using Renderer API
72 let bind_group_layout = renderer.create_bind_group_layout(
73 Some("Texture Bind Group Layout"),
74 &[
75 wgpu::BindGroupLayoutEntry {
76 binding: 0,
77 visibility: wgpu::ShaderStages::FRAGMENT,
78 ty: wgpu::BindingType::Texture {
79 multisampled: false,
80 view_dimension: wgpu::TextureViewDimension::D2,
81 sample_type: wgpu::TextureSampleType::Float { filterable: true },
82 },
83 count: None,
84 },
85 wgpu::BindGroupLayoutEntry {
86 binding: 1,
87 visibility: wgpu::ShaderStages::FRAGMENT,
88 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
89 count: None,
90 },
91 ],
92 );
93
94 let bind_group = renderer.create_bind_group(
95 Some("Texture Bind Group"),
96 &bind_group_layout,
97 &[
98 wgpu::BindGroupEntry {
99 binding: 0,
100 resource: wgpu::BindingResource::TextureView(&texture_view),
101 },
102 wgpu::BindGroupEntry {
103 binding: 1,
104 resource: wgpu::BindingResource::Sampler(&sampler),
105 },
106 ],
107 );
108
109 let pipeline_layout = renderer.create_pipeline_layout(
110 Some("Render Pipeline Layout"),
111 &[&bind_group_layout],
112 &[],
113 );
114
115 // Create pipeline using Renderer API with BlendMode
116 let pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
117 label: Some("Render Pipeline"),
118 layout: Some(&pipeline_layout),
119 vertex: wgpu::VertexState {
120 module: &shader,
121 entry_point: Some("vs_main"),
122 buffers: &[wgpu::VertexBufferLayout {
123 array_stride: 4 * 4,
124 step_mode: wgpu::VertexStepMode::Vertex,
125 attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
126 }],
127 compilation_options: wgpu::PipelineCompilationOptions::default(),
128 },
129 fragment: Some(wgpu::FragmentState {
130 module: &shader,
131 entry_point: Some("fs_main"),
132 // Use BlendMode for transparent rendering
133 targets: &[Some(
134 BlendMode::Alpha.to_color_target_state(wgpu::TextureFormat::Rgba8UnormSrgb),
135 )],
136 compilation_options: wgpu::PipelineCompilationOptions::default(),
137 }),
138 primitive: wgpu::PrimitiveState {
139 topology: wgpu::PrimitiveTopology::TriangleList,
140 strip_index_format: None,
141 front_face: wgpu::FrontFace::Ccw,
142 cull_mode: Some(wgpu::Face::Back),
143 polygon_mode: wgpu::PolygonMode::Fill,
144 unclipped_depth: false,
145 conservative: false,
146 },
147 depth_stencil: None,
148 multisample: wgpu::MultisampleState {
149 count: 1,
150 mask: !0,
151 alpha_to_coverage_enabled: false,
152 },
153 multiview: None,
154 cache: None,
155 });
156
157 #[rustfmt::skip]
158 let vertices: &[f32] = &[
159 -0.8, -0.8, 0.0, 1.0,
160 0.8, -0.8, 1.0, 1.0,
161 0.8, 0.8, 1.0, 0.0,
162 -0.8, -0.8, 0.0, 1.0,
163 0.8, 0.8, 1.0, 0.0,
164 -0.8, 0.8, 0.0, 0.0,
165 ];
166
167 // Create vertex buffer using Renderer helper
168 let vertex_buffer = renderer.create_vertex_buffer(Some("Vertex Buffer"), vertices);
169
170 // Create offscreen framebuffer using the new Framebuffer abstraction
171 let offscreen_fb = Framebuffer::builder(400, 300)
172 .format(wgpu::TextureFormat::Rgba8UnormSrgb)
173 .label("Offscreen FB")
174 .build(graphics_ctx);
175
176 // Create blit shader and pipeline for rendering framebuffer to surface
177 let blit_shader = renderer.create_shader(Some("Blit Shader"), BLIT_SHADER_SOURCE);
178
179 let blit_bind_group_layout = renderer.create_bind_group_layout(
180 Some("Blit Bind Group Layout"),
181 &[
182 wgpu::BindGroupLayoutEntry {
183 binding: 0,
184 visibility: wgpu::ShaderStages::FRAGMENT,
185 ty: wgpu::BindingType::Texture {
186 multisampled: false,
187 view_dimension: wgpu::TextureViewDimension::D2,
188 sample_type: wgpu::TextureSampleType::Float { filterable: true },
189 },
190 count: None,
191 },
192 wgpu::BindGroupLayoutEntry {
193 binding: 1,
194 visibility: wgpu::ShaderStages::FRAGMENT,
195 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
196 count: None,
197 },
198 ],
199 );
200
201 let blit_bind_group = renderer.create_bind_group(
202 Some("Blit Bind Group"),
203 &blit_bind_group_layout,
204 &[
205 wgpu::BindGroupEntry {
206 binding: 0,
207 resource: wgpu::BindingResource::TextureView(offscreen_fb.color_view()),
208 },
209 wgpu::BindGroupEntry {
210 binding: 1,
211 resource: wgpu::BindingResource::Sampler(&sampler),
212 },
213 ],
214 );
215
216 let blit_pipeline_layout = renderer.create_pipeline_layout(
217 Some("Blit Pipeline Layout"),
218 &[&blit_bind_group_layout],
219 &[],
220 );
221
222 let blit_pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
223 label: Some("Blit Pipeline"),
224 layout: Some(&blit_pipeline_layout),
225 vertex: wgpu::VertexState {
226 module: &blit_shader,
227 entry_point: Some("vs_main"),
228 buffers: &[],
229 compilation_options: wgpu::PipelineCompilationOptions::default(),
230 },
231 fragment: Some(wgpu::FragmentState {
232 module: &blit_shader,
233 entry_point: Some("fs_main"),
234 // Use PremultipliedAlpha for framebuffer blitting
235 targets: &[Some(
236 BlendMode::PremultipliedAlpha
237 .to_color_target_state(wgpu::TextureFormat::Bgra8UnormSrgb),
238 )],
239 compilation_options: wgpu::PipelineCompilationOptions::default(),
240 }),
241 primitive: wgpu::PrimitiveState {
242 topology: wgpu::PrimitiveTopology::TriangleList,
243 ..Default::default()
244 },
245 depth_stencil: None,
246 multisample: wgpu::MultisampleState::default(),
247 multiview: None,
248 cache: None,
249 });
250
251 tracing::info!("Renderer initialized successfully");
252 tracing::info!("Device: {:?}", renderer.context().info());
253
254 Box::new(RendererApp {
255 context: graphics_ctx,
256 renderer,
257 window,
258 window_id,
259 pipeline,
260 bind_group,
261 vertex_buffer,
262 offscreen_fb,
263 blit_pipeline,
264 blit_bind_group,
265 time: 0.0,
266 })
267 });
268}Sourcepub fn id(&self) -> WindowId
pub fn id(&self) -> WindowId
Examples found in repository?
examples/multi_window.rs (line 76)
28fn main() {
29 logging::init();
30
31 run_app(|ctx| {
32 let graphics_ctx = GraphicsContext::new_sync();
33
34 let mut windows = HashMap::new();
35
36 // Create 3 windows with different colors
37 let colors = [
38 wgpu::Color {
39 r: 0.8,
40 g: 0.2,
41 b: 0.2,
42 a: 1.0,
43 },
44 wgpu::Color {
45 r: 0.2,
46 g: 0.8,
47 b: 0.2,
48 a: 1.0,
49 },
50 wgpu::Color {
51 r: 0.2,
52 g: 0.2,
53 b: 0.8,
54 a: 1.0,
55 },
56 ];
57
58 for (i, color) in colors.iter().enumerate() {
59 let window = ctx
60 .create_window(WindowDescriptor {
61 title: format!("Window {} - Multi-Window Example", i + 1),
62 size: Some(PhysicalSize::new(400.0, 300.0)),
63 ..Default::default()
64 })
65 .expect("Failed to create window");
66
67 let renderable_window = RenderableWindow::new_with_descriptor(
68 window,
69 graphics_ctx,
70 WindowContextDescriptor {
71 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
72 ..Default::default()
73 },
74 );
75
76 let window_id = renderable_window.id();
77 windows.insert(window_id, (renderable_window, *color));
78 }
79
80 Box::new(App {
81 context: graphics_ctx,
82 windows,
83 })
84 });
85}More examples
examples/sprite_sheet.rs (line 173)
148fn main() {
149 logging::init();
150
151 run_app(|ctx| {
152 let graphics_ctx = GraphicsContext::new_sync();
153 let mut windows = HashMap::new();
154
155 let scale = Window::platform_dpi() as f32;
156 let window = ctx
157 .create_window(WindowDescriptor {
158 title: "Sprite Sheet Animation Example".to_string(),
159 size: Some(PhysicalSize::new(400.0 * scale, 400.0 * scale)),
160 ..Default::default()
161 })
162 .expect("Failed to create window");
163
164 let renderable_window = RenderableWindow::new_with_descriptor(
165 window,
166 graphics_ctx,
167 WindowContextDescriptor {
168 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
169 ..Default::default()
170 },
171 );
172
173 let window_id = renderable_window.id();
174 windows.insert(window_id, renderable_window);
175
176 // Generate sprite sheet
177 let (sprite_data, tex_width, tex_height) = generate_sprite_sheet_data();
178 let sprite_sheet = SpriteSheet::from_data(
179 graphics_ctx,
180 &sprite_data,
181 tex_width,
182 tex_height,
183 SpriteSheetDescriptor {
184 sprite_width: 64,
185 sprite_height: 64,
186 columns: 4,
187 rows: 1,
188 ..Default::default()
189 },
190 );
191
192 // Create animation (4 frames at 8 fps)
193 let animation = SpriteAnimation::new(4, 8.0);
194
195 // Create shader module
196 let shader = graphics_ctx.device.create_shader_module(wgpu::ShaderModuleDescriptor {
197 label: Some("Sprite Shader"),
198 source: wgpu::ShaderSource::Wgsl(SHADER.into()),
199 });
200
201 // Create bind group layout
202 let bind_group_layout = graphics_ctx.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
203 label: Some("Sprite Bind Group Layout"),
204 entries: &[
205 wgpu::BindGroupLayoutEntry {
206 binding: 0,
207 visibility: wgpu::ShaderStages::VERTEX,
208 ty: wgpu::BindingType::Buffer {
209 ty: wgpu::BufferBindingType::Uniform,
210 has_dynamic_offset: false,
211 min_binding_size: None,
212 },
213 count: None,
214 },
215 wgpu::BindGroupLayoutEntry {
216 binding: 1,
217 visibility: wgpu::ShaderStages::FRAGMENT,
218 ty: wgpu::BindingType::Texture {
219 sample_type: wgpu::TextureSampleType::Float { filterable: true },
220 view_dimension: wgpu::TextureViewDimension::D2,
221 multisampled: false,
222 },
223 count: None,
224 },
225 wgpu::BindGroupLayoutEntry {
226 binding: 2,
227 visibility: wgpu::ShaderStages::FRAGMENT,
228 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
229 count: None,
230 },
231 ],
232 });
233
234 // Create pipeline layout
235 let pipeline_layout = graphics_ctx.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
236 label: Some("Sprite Pipeline Layout"),
237 bind_group_layouts: &[&bind_group_layout],
238 push_constant_ranges: &[],
239 });
240
241 // Create render pipeline
242 let pipeline = graphics_ctx.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
243 label: Some("Sprite Pipeline"),
244 layout: Some(&pipeline_layout),
245 vertex: wgpu::VertexState {
246 module: &shader,
247 entry_point: Some("vs_main"),
248 buffers: &[wgpu::VertexBufferLayout {
249 array_stride: std::mem::size_of::<Vertex>() as u64,
250 step_mode: wgpu::VertexStepMode::Vertex,
251 attributes: &[
252 wgpu::VertexAttribute {
253 offset: 0,
254 shader_location: 0,
255 format: wgpu::VertexFormat::Float32x2,
256 },
257 wgpu::VertexAttribute {
258 offset: 8,
259 shader_location: 1,
260 format: wgpu::VertexFormat::Float32x2,
261 },
262 ],
263 }],
264 compilation_options: wgpu::PipelineCompilationOptions::default(),
265 },
266 fragment: Some(wgpu::FragmentState {
267 module: &shader,
268 entry_point: Some("fs_main"),
269 targets: &[Some(wgpu::ColorTargetState {
270 format: wgpu::TextureFormat::Bgra8UnormSrgb,
271 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
272 write_mask: wgpu::ColorWrites::ALL,
273 })],
274 compilation_options: wgpu::PipelineCompilationOptions::default(),
275 }),
276 primitive: wgpu::PrimitiveState {
277 topology: wgpu::PrimitiveTopology::TriangleList,
278 ..Default::default()
279 },
280 depth_stencil: None,
281 multisample: wgpu::MultisampleState::default(),
282 multiview: None,
283 cache: None,
284 });
285
286 // Create uniform buffer
287 let uniforms = Uniforms {
288 mvp: [
289 [1.0, 0.0, 0.0, 0.0],
290 [0.0, 1.0, 0.0, 0.0],
291 [0.0, 0.0, 1.0, 0.0],
292 [0.0, 0.0, 0.0, 1.0],
293 ],
294 };
295 let uniform_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
296 label: Some("Uniform Buffer"),
297 contents: bytemuck::cast_slice(&[uniforms]),
298 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
299 });
300
301 // Create sampler
302 let sampler = graphics_ctx.device.create_sampler(&wgpu::SamplerDescriptor {
303 label: Some("Sprite Sampler"),
304 mag_filter: wgpu::FilterMode::Linear,
305 min_filter: wgpu::FilterMode::Linear,
306 ..Default::default()
307 });
308
309 // Create bind group
310 let bind_group = graphics_ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
311 label: Some("Sprite Bind Group"),
312 layout: &bind_group_layout,
313 entries: &[
314 wgpu::BindGroupEntry {
315 binding: 0,
316 resource: uniform_buffer.as_entire_binding(),
317 },
318 wgpu::BindGroupEntry {
319 binding: 1,
320 resource: wgpu::BindingResource::TextureView(sprite_sheet.view()),
321 },
322 wgpu::BindGroupEntry {
323 binding: 2,
324 resource: wgpu::BindingResource::Sampler(&sampler),
325 },
326 ],
327 });
328
329 // Initial vertex buffer (will be updated each frame with new UVs)
330 let vertices = create_quad_vertices(0.0, 0.0, 1.0, 1.0);
331 let vertex_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
332 label: Some("Vertex Buffer"),
333 contents: bytemuck::cast_slice(&vertices),
334 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
335 });
336
337 Box::new(App {
338 _context: graphics_ctx,
339 windows,
340 pipeline,
341 bind_group,
342 vertex_buffer,
343 uniform_buffer,
344 sprite_sheet,
345 animation,
346 last_update: Instant::now(),
347 })
348 });
349}examples/textured_window.rs (line 224)
19fn main() {
20 logging::init();
21
22 run_app(|ctx| {
23 let graphics_ctx = GraphicsContext::new_sync();
24
25 let window = ctx
26 .create_window(WindowDescriptor {
27 title: "Textured Window".to_string(),
28 ..Default::default()
29 })
30 .expect("Failed to create window");
31
32 let window = RenderableWindow::new_with_descriptor(
33 window,
34 graphics_ctx,
35 WindowContextDescriptor {
36 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
37 ..Default::default()
38 },
39 );
40
41 let shader = graphics_ctx
42 .device
43 .create_shader_module(wgpu::ShaderModuleDescriptor {
44 label: Some("Texture Shader"),
45 source: wgpu::ShaderSource::Wgsl(include_str!("textured_window.wgsl").into()),
46 });
47
48 let texture_size = wgpu::Extent3d {
49 width: 256,
50 height: 256,
51 depth_or_array_layers: 1,
52 };
53
54 let texture = graphics_ctx
55 .device
56 .create_texture(&wgpu::TextureDescriptor {
57 label: Some("Example Texture"),
58 size: texture_size,
59 mip_level_count: 1,
60 sample_count: 1,
61 dimension: wgpu::TextureDimension::D2,
62 format: wgpu::TextureFormat::Rgba8UnormSrgb,
63 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
64 view_formats: &[],
65 });
66
67 let mut texture_data = vec![0u8; (256 * 256 * 4) as usize];
68 for y in 0..256 {
69 for x in 0..256 {
70 let idx = ((y * 256 + x) * 4) as usize;
71 texture_data[idx] = x as u8;
72 texture_data[idx + 1] = y as u8;
73 texture_data[idx + 2] = ((x + y) / 2) as u8;
74 texture_data[idx + 3] = 255;
75 }
76 }
77
78 graphics_ctx.queue.write_texture(
79 wgpu::TexelCopyTextureInfo {
80 texture: &texture,
81 mip_level: 0,
82 origin: wgpu::Origin3d::ZERO,
83 aspect: wgpu::TextureAspect::All,
84 },
85 &texture_data,
86 wgpu::TexelCopyBufferLayout {
87 offset: 0,
88 bytes_per_row: Some(256 * 4),
89 rows_per_image: Some(256),
90 },
91 texture_size,
92 );
93
94 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
95 let sampler = graphics_ctx
96 .device
97 .create_sampler(&wgpu::SamplerDescriptor {
98 address_mode_u: wgpu::AddressMode::ClampToEdge,
99 address_mode_v: wgpu::AddressMode::ClampToEdge,
100 address_mode_w: wgpu::AddressMode::ClampToEdge,
101 mag_filter: wgpu::FilterMode::Linear,
102 min_filter: wgpu::FilterMode::Nearest,
103 mipmap_filter: wgpu::FilterMode::Nearest,
104 ..Default::default()
105 });
106
107 let bind_group_layout =
108 graphics_ctx
109 .device
110 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
111 label: Some("Texture Bind Group Layout"),
112 entries: &[
113 wgpu::BindGroupLayoutEntry {
114 binding: 0,
115 visibility: wgpu::ShaderStages::FRAGMENT,
116 ty: wgpu::BindingType::Texture {
117 multisampled: false,
118 view_dimension: wgpu::TextureViewDimension::D2,
119 sample_type: wgpu::TextureSampleType::Float { filterable: true },
120 },
121 count: None,
122 },
123 wgpu::BindGroupLayoutEntry {
124 binding: 1,
125 visibility: wgpu::ShaderStages::FRAGMENT,
126 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
127 count: None,
128 },
129 ],
130 });
131
132 let bind_group = graphics_ctx
133 .device
134 .create_bind_group(&wgpu::BindGroupDescriptor {
135 label: Some("Texture Bind Group"),
136 layout: &bind_group_layout,
137 entries: &[
138 wgpu::BindGroupEntry {
139 binding: 0,
140 resource: wgpu::BindingResource::TextureView(&texture_view),
141 },
142 wgpu::BindGroupEntry {
143 binding: 1,
144 resource: wgpu::BindingResource::Sampler(&sampler),
145 },
146 ],
147 });
148
149 let pipeline_layout =
150 graphics_ctx
151 .device
152 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
153 label: Some("Render Pipeline Layout"),
154 bind_group_layouts: &[&bind_group_layout],
155 push_constant_ranges: &[],
156 });
157
158 let pipeline =
159 graphics_ctx
160 .device
161 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
162 label: Some("Render Pipeline"),
163 layout: Some(&pipeline_layout),
164 vertex: wgpu::VertexState {
165 module: &shader,
166 entry_point: Some("vs_main"),
167 buffers: &[wgpu::VertexBufferLayout {
168 array_stride: 4 * 4,
169 step_mode: wgpu::VertexStepMode::Vertex,
170 attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
171 }],
172 compilation_options: wgpu::PipelineCompilationOptions::default(),
173 },
174 fragment: Some(wgpu::FragmentState {
175 module: &shader,
176 entry_point: Some("fs_main"),
177 targets: &[Some(wgpu::ColorTargetState {
178 format: wgpu::TextureFormat::Bgra8UnormSrgb,
179 blend: Some(wgpu::BlendState::REPLACE),
180 write_mask: wgpu::ColorWrites::ALL,
181 })],
182 compilation_options: wgpu::PipelineCompilationOptions::default(),
183 }),
184 primitive: wgpu::PrimitiveState {
185 topology: wgpu::PrimitiveTopology::TriangleList,
186 strip_index_format: None,
187 front_face: wgpu::FrontFace::Ccw,
188 cull_mode: Some(wgpu::Face::Back),
189 polygon_mode: wgpu::PolygonMode::Fill,
190 unclipped_depth: false,
191 conservative: false,
192 },
193 depth_stencil: None,
194 multisample: wgpu::MultisampleState {
195 count: 1,
196 mask: !0,
197 alpha_to_coverage_enabled: false,
198 },
199 multiview: None,
200 cache: None,
201 });
202
203 #[rustfmt::skip]
204 let vertices: &[f32] = &[
205 -0.8, -0.8, 0.0, 1.0,
206 0.8, -0.8, 1.0, 1.0,
207 0.8, 0.8, 1.0, 0.0,
208 -0.8, -0.8, 0.0, 1.0,
209 0.8, 0.8, 1.0, 0.0,
210 -0.8, 0.8, 0.0, 0.0,
211 ];
212
213 let vertex_buffer = graphics_ctx.device.create_buffer(&wgpu::BufferDescriptor {
214 label: Some("Vertex Buffer"),
215 size: (vertices.len() * std::mem::size_of::<f32>()) as u64,
216 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
217 mapped_at_creation: false,
218 });
219
220 graphics_ctx
221 .queue
222 .write_buffer(&vertex_buffer, 0, bytemuck::cast_slice(vertices));
223
224 let window_id = window.id();
225
226 Box::new(App {
227 window,
228 window_id,
229 pipeline,
230 bind_group,
231 vertex_buffer,
232 })
233 });
234}examples/image_blitting.rs (line 192)
167fn main() {
168 logging::init();
169
170 run_app(|ctx| {
171 let graphics_ctx = GraphicsContext::new_sync();
172 let mut windows = HashMap::new();
173
174 let scale = Window::platform_dpi() as f32;
175 let window = ctx
176 .create_window(WindowDescriptor {
177 title: "Image Blitting Example".to_string(),
178 size: Some(PhysicalSize::new(800.0 * scale, 600.0 * scale)),
179 ..Default::default()
180 })
181 .expect("Failed to create window");
182
183 let renderable_window = RenderableWindow::new_with_descriptor(
184 window,
185 graphics_ctx,
186 WindowContextDescriptor {
187 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
188 ..Default::default()
189 },
190 );
191
192 let window_id = renderable_window.id();
193 windows.insert(window_id, renderable_window);
194
195 // Create shader module
196 let shader = graphics_ctx.device.create_shader_module(wgpu::ShaderModuleDescriptor {
197 label: Some("Blit Shader"),
198 source: wgpu::ShaderSource::Wgsl(SHADER.into()),
199 });
200
201 // Create bind group layout
202 let bind_group_layout = graphics_ctx.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
203 label: Some("Blit Bind Group Layout"),
204 entries: &[
205 wgpu::BindGroupLayoutEntry {
206 binding: 0,
207 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
208 ty: wgpu::BindingType::Buffer {
209 ty: wgpu::BufferBindingType::Uniform,
210 has_dynamic_offset: false,
211 min_binding_size: None,
212 },
213 count: None,
214 },
215 wgpu::BindGroupLayoutEntry {
216 binding: 1,
217 visibility: wgpu::ShaderStages::FRAGMENT,
218 ty: wgpu::BindingType::Texture {
219 sample_type: wgpu::TextureSampleType::Float { filterable: true },
220 view_dimension: wgpu::TextureViewDimension::D2,
221 multisampled: false,
222 },
223 count: None,
224 },
225 wgpu::BindGroupLayoutEntry {
226 binding: 2,
227 visibility: wgpu::ShaderStages::FRAGMENT,
228 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
229 count: None,
230 },
231 ],
232 });
233
234 // Create pipeline layout
235 let pipeline_layout = graphics_ctx.device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
236 label: Some("Blit Pipeline Layout"),
237 bind_group_layouts: &[&bind_group_layout],
238 push_constant_ranges: &[],
239 });
240
241 // Create render pipeline
242 let pipeline = graphics_ctx.device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
243 label: Some("Blit Pipeline"),
244 layout: Some(&pipeline_layout),
245 vertex: wgpu::VertexState {
246 module: &shader,
247 entry_point: Some("vs_main"),
248 buffers: &[wgpu::VertexBufferLayout {
249 array_stride: std::mem::size_of::<Vertex>() as u64,
250 step_mode: wgpu::VertexStepMode::Vertex,
251 attributes: &[
252 wgpu::VertexAttribute {
253 offset: 0,
254 shader_location: 0,
255 format: wgpu::VertexFormat::Float32x2,
256 },
257 wgpu::VertexAttribute {
258 offset: 8,
259 shader_location: 1,
260 format: wgpu::VertexFormat::Float32x2,
261 },
262 ],
263 }],
264 compilation_options: wgpu::PipelineCompilationOptions::default(),
265 },
266 fragment: Some(wgpu::FragmentState {
267 module: &shader,
268 entry_point: Some("fs_main"),
269 targets: &[Some(wgpu::ColorTargetState {
270 format: wgpu::TextureFormat::Bgra8UnormSrgb,
271 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
272 write_mask: wgpu::ColorWrites::ALL,
273 })],
274 compilation_options: wgpu::PipelineCompilationOptions::default(),
275 }),
276 primitive: wgpu::PrimitiveState {
277 topology: wgpu::PrimitiveTopology::TriangleList,
278 strip_index_format: None,
279 front_face: wgpu::FrontFace::Ccw,
280 cull_mode: None,
281 polygon_mode: wgpu::PolygonMode::Fill,
282 unclipped_depth: false,
283 conservative: false,
284 },
285 depth_stencil: None,
286 multisample: wgpu::MultisampleState::default(),
287 multiview: None,
288 cache: None,
289 });
290
291 // Create vertex buffer for a fullscreen quad
292 let vertices = [
293 Vertex { position: [-0.8, -0.8], uv: [0.0, 1.0] },
294 Vertex { position: [0.8, -0.8], uv: [1.0, 1.0] },
295 Vertex { position: [0.8, 0.8], uv: [1.0, 0.0] },
296 Vertex { position: [-0.8, -0.8], uv: [0.0, 1.0] },
297 Vertex { position: [0.8, 0.8], uv: [1.0, 0.0] },
298 Vertex { position: [-0.8, 0.8], uv: [0.0, 0.0] },
299 ];
300 let vertex_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
301 label: Some("Vertex Buffer"),
302 contents: bytemuck::cast_slice(&vertices),
303 usage: wgpu::BufferUsages::VERTEX,
304 });
305
306 // Create uniform buffer
307 let uniforms = Uniforms {
308 mvp: [
309 [1.0, 0.0, 0.0, 0.0],
310 [0.0, 1.0, 0.0, 0.0],
311 [0.0, 0.0, 1.0, 0.0],
312 [0.0, 0.0, 0.0, 1.0],
313 ],
314 tint: [1.0, 1.0, 1.0, 1.0],
315 };
316 let uniform_buffer = graphics_ctx.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
317 label: Some("Uniform Buffer"),
318 contents: bytemuck::cast_slice(&[uniforms]),
319 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
320 });
321
322 // Create CPU-side image buffer
323 let mut image_buffer = ImageBuffer::new(256, 256);
324 image_buffer.clear(30, 30, 40, 255);
325
326 // Create GPU texture
327 let texture = graphics_ctx.device.create_texture(&wgpu::TextureDescriptor {
328 label: Some("Blit Texture"),
329 size: wgpu::Extent3d {
330 width: 256,
331 height: 256,
332 depth_or_array_layers: 1,
333 },
334 mip_level_count: 1,
335 sample_count: 1,
336 dimension: wgpu::TextureDimension::D2,
337 format: wgpu::TextureFormat::Rgba8UnormSrgb,
338 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
339 view_formats: &[],
340 });
341
342 // Create texture view and sampler
343 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
344 let sampler = graphics_ctx.device.create_sampler(&wgpu::SamplerDescriptor {
345 label: Some("Blit Sampler"),
346 address_mode_u: wgpu::AddressMode::ClampToEdge,
347 address_mode_v: wgpu::AddressMode::ClampToEdge,
348 address_mode_w: wgpu::AddressMode::ClampToEdge,
349 mag_filter: wgpu::FilterMode::Nearest, // Pixel-perfect rendering
350 min_filter: wgpu::FilterMode::Nearest,
351 mipmap_filter: wgpu::FilterMode::Nearest,
352 ..Default::default()
353 });
354
355 // Create bind group
356 let bind_group = graphics_ctx.device.create_bind_group(&wgpu::BindGroupDescriptor {
357 label: Some("Blit Bind Group"),
358 layout: &bind_group_layout,
359 entries: &[
360 wgpu::BindGroupEntry {
361 binding: 0,
362 resource: uniform_buffer.as_entire_binding(),
363 },
364 wgpu::BindGroupEntry {
365 binding: 1,
366 resource: wgpu::BindingResource::TextureView(&texture_view),
367 },
368 wgpu::BindGroupEntry {
369 binding: 2,
370 resource: wgpu::BindingResource::Sampler(&sampler),
371 },
372 ],
373 });
374
375 Box::new(App {
376 context: graphics_ctx,
377 windows,
378 pipeline,
379 bind_group_layout,
380 vertex_buffer,
381 texture,
382 bind_group,
383 uniform_buffer,
384 image_buffer,
385 start_time: Instant::now(),
386 })
387 });
388}examples/renderer_api.rs (line 52)
28fn main() {
29 logging::init();
30
31 run_app(|ctx| {
32 let graphics_ctx = GraphicsContext::new_sync();
33 let renderer = Renderer::new(graphics_ctx);
34
35 let window = ctx
36 .create_window(WindowDescriptor {
37 title: "Renderer API Example".to_string(),
38 size: Some(PhysicalSize::new(800.0, 600.0)),
39 ..Default::default()
40 })
41 .expect("Failed to create window");
42
43 let window = RenderableWindow::new_with_descriptor(
44 window,
45 graphics_ctx,
46 WindowContextDescriptor {
47 format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48 ..Default::default()
49 },
50 );
51
52 let window_id = window.id();
53
54 // Create shader using Renderer API
55 let shader = renderer.create_shader(Some("Color Shader"), SHADER_SOURCE);
56
57 // Create texture using Renderer helper
58 let texture_data = create_gradient_texture();
59 let texture = renderer.create_texture_2d(
60 Some("Gradient Texture"),
61 256,
62 256,
63 wgpu::TextureFormat::Rgba8UnormSrgb,
64 wgpu::TextureUsages::TEXTURE_BINDING,
65 &texture_data,
66 );
67
68 let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
69 let sampler = renderer.create_linear_sampler(Some("Linear Sampler"));
70
71 // Create bind group using Renderer API
72 let bind_group_layout = renderer.create_bind_group_layout(
73 Some("Texture Bind Group Layout"),
74 &[
75 wgpu::BindGroupLayoutEntry {
76 binding: 0,
77 visibility: wgpu::ShaderStages::FRAGMENT,
78 ty: wgpu::BindingType::Texture {
79 multisampled: false,
80 view_dimension: wgpu::TextureViewDimension::D2,
81 sample_type: wgpu::TextureSampleType::Float { filterable: true },
82 },
83 count: None,
84 },
85 wgpu::BindGroupLayoutEntry {
86 binding: 1,
87 visibility: wgpu::ShaderStages::FRAGMENT,
88 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
89 count: None,
90 },
91 ],
92 );
93
94 let bind_group = renderer.create_bind_group(
95 Some("Texture Bind Group"),
96 &bind_group_layout,
97 &[
98 wgpu::BindGroupEntry {
99 binding: 0,
100 resource: wgpu::BindingResource::TextureView(&texture_view),
101 },
102 wgpu::BindGroupEntry {
103 binding: 1,
104 resource: wgpu::BindingResource::Sampler(&sampler),
105 },
106 ],
107 );
108
109 let pipeline_layout = renderer.create_pipeline_layout(
110 Some("Render Pipeline Layout"),
111 &[&bind_group_layout],
112 &[],
113 );
114
115 // Create pipeline using Renderer API with BlendMode
116 let pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
117 label: Some("Render Pipeline"),
118 layout: Some(&pipeline_layout),
119 vertex: wgpu::VertexState {
120 module: &shader,
121 entry_point: Some("vs_main"),
122 buffers: &[wgpu::VertexBufferLayout {
123 array_stride: 4 * 4,
124 step_mode: wgpu::VertexStepMode::Vertex,
125 attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2],
126 }],
127 compilation_options: wgpu::PipelineCompilationOptions::default(),
128 },
129 fragment: Some(wgpu::FragmentState {
130 module: &shader,
131 entry_point: Some("fs_main"),
132 // Use BlendMode for transparent rendering
133 targets: &[Some(
134 BlendMode::Alpha.to_color_target_state(wgpu::TextureFormat::Rgba8UnormSrgb),
135 )],
136 compilation_options: wgpu::PipelineCompilationOptions::default(),
137 }),
138 primitive: wgpu::PrimitiveState {
139 topology: wgpu::PrimitiveTopology::TriangleList,
140 strip_index_format: None,
141 front_face: wgpu::FrontFace::Ccw,
142 cull_mode: Some(wgpu::Face::Back),
143 polygon_mode: wgpu::PolygonMode::Fill,
144 unclipped_depth: false,
145 conservative: false,
146 },
147 depth_stencil: None,
148 multisample: wgpu::MultisampleState {
149 count: 1,
150 mask: !0,
151 alpha_to_coverage_enabled: false,
152 },
153 multiview: None,
154 cache: None,
155 });
156
157 #[rustfmt::skip]
158 let vertices: &[f32] = &[
159 -0.8, -0.8, 0.0, 1.0,
160 0.8, -0.8, 1.0, 1.0,
161 0.8, 0.8, 1.0, 0.0,
162 -0.8, -0.8, 0.0, 1.0,
163 0.8, 0.8, 1.0, 0.0,
164 -0.8, 0.8, 0.0, 0.0,
165 ];
166
167 // Create vertex buffer using Renderer helper
168 let vertex_buffer = renderer.create_vertex_buffer(Some("Vertex Buffer"), vertices);
169
170 // Create offscreen framebuffer using the new Framebuffer abstraction
171 let offscreen_fb = Framebuffer::builder(400, 300)
172 .format(wgpu::TextureFormat::Rgba8UnormSrgb)
173 .label("Offscreen FB")
174 .build(graphics_ctx);
175
176 // Create blit shader and pipeline for rendering framebuffer to surface
177 let blit_shader = renderer.create_shader(Some("Blit Shader"), BLIT_SHADER_SOURCE);
178
179 let blit_bind_group_layout = renderer.create_bind_group_layout(
180 Some("Blit Bind Group Layout"),
181 &[
182 wgpu::BindGroupLayoutEntry {
183 binding: 0,
184 visibility: wgpu::ShaderStages::FRAGMENT,
185 ty: wgpu::BindingType::Texture {
186 multisampled: false,
187 view_dimension: wgpu::TextureViewDimension::D2,
188 sample_type: wgpu::TextureSampleType::Float { filterable: true },
189 },
190 count: None,
191 },
192 wgpu::BindGroupLayoutEntry {
193 binding: 1,
194 visibility: wgpu::ShaderStages::FRAGMENT,
195 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
196 count: None,
197 },
198 ],
199 );
200
201 let blit_bind_group = renderer.create_bind_group(
202 Some("Blit Bind Group"),
203 &blit_bind_group_layout,
204 &[
205 wgpu::BindGroupEntry {
206 binding: 0,
207 resource: wgpu::BindingResource::TextureView(offscreen_fb.color_view()),
208 },
209 wgpu::BindGroupEntry {
210 binding: 1,
211 resource: wgpu::BindingResource::Sampler(&sampler),
212 },
213 ],
214 );
215
216 let blit_pipeline_layout = renderer.create_pipeline_layout(
217 Some("Blit Pipeline Layout"),
218 &[&blit_bind_group_layout],
219 &[],
220 );
221
222 let blit_pipeline = renderer.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
223 label: Some("Blit Pipeline"),
224 layout: Some(&blit_pipeline_layout),
225 vertex: wgpu::VertexState {
226 module: &blit_shader,
227 entry_point: Some("vs_main"),
228 buffers: &[],
229 compilation_options: wgpu::PipelineCompilationOptions::default(),
230 },
231 fragment: Some(wgpu::FragmentState {
232 module: &blit_shader,
233 entry_point: Some("fs_main"),
234 // Use PremultipliedAlpha for framebuffer blitting
235 targets: &[Some(
236 BlendMode::PremultipliedAlpha
237 .to_color_target_state(wgpu::TextureFormat::Bgra8UnormSrgb),
238 )],
239 compilation_options: wgpu::PipelineCompilationOptions::default(),
240 }),
241 primitive: wgpu::PrimitiveState {
242 topology: wgpu::PrimitiveTopology::TriangleList,
243 ..Default::default()
244 },
245 depth_stencil: None,
246 multisample: wgpu::MultisampleState::default(),
247 multiview: None,
248 cache: None,
249 });
250
251 tracing::info!("Renderer initialized successfully");
252 tracing::info!("Device: {:?}", renderer.context().info());
253
254 Box::new(RendererApp {
255 context: graphics_ctx,
256 renderer,
257 window,
258 window_id,
259 pipeline,
260 bind_group,
261 vertex_buffer,
262 offscreen_fb,
263 blit_pipeline,
264 blit_bind_group,
265 time: 0.0,
266 })
267 });
268}pub fn window(&self) -> &Window
Sourcepub fn context(&self) -> &WindowContext
pub fn context(&self) -> &WindowContext
Examples found in repository?
examples/sprite_sheet.rs (line 377)
363 fn update(&mut self, _ctx: &mut astrelis_winit::app::AppCtx) {
364 let now = Instant::now();
365 let dt = now.duration_since(self.last_update).as_secs_f32();
366 self.last_update = now;
367
368 // Update animation
369 if self.animation.update(dt) {
370 // Frame changed - update vertex buffer with new UVs
371 let frame = self.animation.current_frame();
372 let uv = self.sprite_sheet.sprite_uv(frame);
373 let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
374
375 // Get context from first window
376 if let Some(window) = self.windows.values().next() {
377 window.context().graphics_context().queue.write_buffer(
378 &self.vertex_buffer,
379 0,
380 bytemuck::cast_slice(&vertices),
381 );
382 }
383 }
384 }pub fn context_mut(&mut self) -> &mut WindowContext
Sourcepub fn resized(&mut self, new_size: Size<u32>)
pub fn resized(&mut self, new_size: Size<u32>)
Handle window resize event
Examples found in repository?
examples/multi_window.rs (line 107)
93 fn render(
94 &mut self,
95 _ctx: &mut astrelis_winit::app::AppCtx,
96 window_id: WindowId,
97 events: &mut astrelis_winit::event::EventBatch,
98 ) {
99 // Get the window and color for this specific window
100 let Some((window, color)) = self.windows.get_mut(&window_id) else {
101 return;
102 };
103
104 // Handle window-specific resize events
105 events.dispatch(|event| {
106 if let astrelis_winit::event::Event::WindowResized(size) = event {
107 window.resized(*size);
108 astrelis_winit::event::HandleStatus::consumed()
109 } else {
110 astrelis_winit::event::HandleStatus::ignored()
111 }
112 });
113
114 // Render this specific window
115 let mut frame = window.begin_drawing();
116
117 {
118 let _render_pass = RenderPassBuilder::new()
119 .label("Multi-Window Render Pass")
120 .target(RenderTarget::Surface)
121 .clear_color(*color)
122 .build(&mut frame);
123 }
124
125 frame.finish();
126 }More examples
examples/image_blitting.rs (line 457)
444 fn render(
445 &mut self,
446 _ctx: &mut astrelis_winit::app::AppCtx,
447 window_id: WindowId,
448 events: &mut astrelis_winit::event::EventBatch,
449 ) {
450 let Some(window) = self.windows.get_mut(&window_id) else {
451 return;
452 };
453
454 // Handle resize
455 events.dispatch(|event| {
456 if let astrelis_winit::event::Event::WindowResized(size) = event {
457 window.resized(*size);
458 astrelis_winit::event::HandleStatus::consumed()
459 } else {
460 astrelis_winit::event::HandleStatus::ignored()
461 }
462 });
463
464 let mut frame = window.begin_drawing();
465
466 {
467 let mut render_pass = RenderPassBuilder::new()
468 .label("Blit Render Pass")
469 .target(RenderTarget::Surface)
470 .clear_color(wgpu::Color {
471 r: 0.05,
472 g: 0.05,
473 b: 0.08,
474 a: 1.0,
475 })
476 .build(&mut frame);
477
478 let pass = render_pass.descriptor();
479 pass.set_pipeline(&self.pipeline);
480 pass.set_bind_group(0, &self.bind_group, &[]);
481 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
482 pass.draw(0..6, 0..1);
483 }
484
485 frame.finish();
486 }examples/sprite_sheet.rs (line 399)
386 fn render(
387 &mut self,
388 _ctx: &mut astrelis_winit::app::AppCtx,
389 window_id: WindowId,
390 events: &mut astrelis_winit::event::EventBatch,
391 ) {
392 let Some(window) = self.windows.get_mut(&window_id) else {
393 return;
394 };
395
396 // Handle resize
397 events.dispatch(|event| {
398 if let astrelis_winit::event::Event::WindowResized(size) = event {
399 window.resized(*size);
400 astrelis_winit::event::HandleStatus::consumed()
401 } else {
402 astrelis_winit::event::HandleStatus::ignored()
403 }
404 });
405
406 let mut frame = window.begin_drawing();
407
408 {
409 let mut render_pass = RenderPassBuilder::new()
410 .label("Sprite Render Pass")
411 .target(RenderTarget::Surface)
412 .clear_color(wgpu::Color {
413 r: 0.1,
414 g: 0.1,
415 b: 0.15,
416 a: 1.0,
417 })
418 .build(&mut frame);
419
420 let pass = render_pass.descriptor();
421 pass.set_pipeline(&self.pipeline);
422 pass.set_bind_group(0, &self.bind_group, &[]);
423 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
424 pass.draw(0..6, 0..1);
425 }
426
427 frame.finish();
428 }examples/textured_window.rs (line 254)
241 fn render(
242 &mut self,
243 _ctx: &mut astrelis_winit::app::AppCtx,
244 window_id: WindowId,
245 events: &mut astrelis_winit::event::EventBatch,
246 ) {
247 if window_id != self.window_id {
248 return;
249 }
250
251 // Handle window resize events
252 events.dispatch(|event| {
253 if let astrelis_winit::event::Event::WindowResized(size) = event {
254 self.window.resized(*size);
255 astrelis_winit::event::HandleStatus::consumed()
256 } else {
257 astrelis_winit::event::HandleStatus::ignored()
258 }
259 });
260
261 let mut frame = self.window.begin_drawing();
262
263 // Using new simplified RenderPassBuilder API with RenderTarget
264 {
265 let mut render_pass = RenderPassBuilder::new()
266 .label("Render Pass")
267 .target(RenderTarget::Surface)
268 .clear_color(wgpu::Color {
269 r: 0.1,
270 g: 0.2,
271 b: 0.3,
272 a: 1.0,
273 })
274 .build(&mut frame);
275
276 let pass = render_pass.descriptor();
277 pass.set_pipeline(&self.pipeline);
278 pass.set_bind_group(0, &self.bind_group, &[]);
279 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
280 pass.draw(0..6, 0..1);
281 }
282
283 frame.finish();
284 }examples/renderer_api.rs (line 284)
276 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
277 if window_id != self.window_id {
278 return;
279 }
280
281 // Handle window-specific resize events
282 events.dispatch(|event| {
283 if let astrelis_winit::event::Event::WindowResized(size) = event {
284 self.window.resized(*size);
285 astrelis_winit::event::HandleStatus::consumed()
286 } else {
287 astrelis_winit::event::HandleStatus::ignored()
288 }
289 });
290
291 let mut frame = self.window.begin_drawing();
292
293 // Pass 1: Render to offscreen framebuffer using new simplified API
294 {
295 let mut render_pass = RenderPassBuilder::new()
296 .label("Offscreen Pass")
297 .target(RenderTarget::Framebuffer(&self.offscreen_fb))
298 .clear_color(wgpu::Color {
299 r: 0.2,
300 g: 0.1,
301 b: 0.3,
302 a: 1.0,
303 })
304 .build(&mut frame);
305
306 let pass = render_pass.descriptor();
307 pass.set_pipeline(&self.pipeline);
308 pass.set_bind_group(0, &self.bind_group, &[]);
309 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
310 pass.draw(0..6, 0..1);
311 }
312
313 // Pass 2: Blit framebuffer to surface using new simplified API
314 {
315 let mut render_pass = RenderPassBuilder::new()
316 .label("Surface Pass")
317 .target(RenderTarget::Surface)
318 .clear_color(wgpu::Color {
319 r: 0.1,
320 g: 0.2,
321 b: 0.3,
322 a: 1.0,
323 })
324 .build(&mut frame);
325
326 let pass = render_pass.descriptor();
327 pass.set_pipeline(&self.blit_pipeline);
328 pass.set_bind_group(0, &self.blit_bind_group, &[]);
329 // Draw fullscreen triangle
330 pass.draw(0..3, 0..1);
331 }
332
333 frame.finish();
334 }Sourcepub fn inner_size(&self) -> PhysicalSize<u32>
pub fn inner_size(&self) -> PhysicalSize<u32>
Get the inner size of the window.
pub fn scale_factor(&self) -> f64
pub fn viewport(&self) -> Viewport
Methods from Deref<Target = WindowContext>§
pub fn window(&self) -> &Window
Sourcepub fn graphics_context(&self) -> &GraphicsContext
pub fn graphics_context(&self) -> &GraphicsContext
Examples found in repository?
examples/sprite_sheet.rs (line 377)
363 fn update(&mut self, _ctx: &mut astrelis_winit::app::AppCtx) {
364 let now = Instant::now();
365 let dt = now.duration_since(self.last_update).as_secs_f32();
366 self.last_update = now;
367
368 // Update animation
369 if self.animation.update(dt) {
370 // Frame changed - update vertex buffer with new UVs
371 let frame = self.animation.current_frame();
372 let uv = self.sprite_sheet.sprite_uv(frame);
373 let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
374
375 // Get context from first window
376 if let Some(window) = self.windows.values().next() {
377 window.context().graphics_context().queue.write_buffer(
378 &self.vertex_buffer,
379 0,
380 bytemuck::cast_slice(&vertices),
381 );
382 }
383 }
384 }pub fn surface(&self) -> &Surface<'static>
pub fn surface_config(&self) -> &SurfaceConfiguration
pub fn size_f32(&self) -> Size<f32>
Sourcepub fn inner_size(&self) -> PhysicalSize<u32>
pub fn inner_size(&self) -> PhysicalSize<u32>
Get the inner size of the window.
Sourcepub fn reconfigure_surface(&mut self, config: SurfaceConfiguration)
pub fn reconfigure_surface(&mut self, config: SurfaceConfiguration)
Reconfigure the surface with a new configuration.
Trait Implementations§
Source§impl Deref for RenderableWindow
impl Deref for RenderableWindow
Source§impl DerefMut for RenderableWindow
impl DerefMut for RenderableWindow
Source§impl WindowBackend for RenderableWindow
impl WindowBackend for RenderableWindow
type FrameContext = FrameContext
fn begin_drawing(&mut self) -> Self::FrameContext
Auto Trait Implementations§
impl !Freeze for RenderableWindow
impl !RefUnwindSafe for RenderableWindow
impl Send for RenderableWindow
impl Sync for RenderableWindow
impl Unpin for RenderableWindow
impl !UnwindSafe for RenderableWindow
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
Mutably borrows from an owned value. Read more
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>
Convert
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>
Convert
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)
Convert
&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)
Convert
&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>
Converts
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>
Converts
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