From 0127f5704526433ee360450eea542018a955d3a2 Mon Sep 17 00:00:00 2001 From: Chance Date: Sun, 20 Apr 2025 14:47:03 -0400 Subject: [PATCH] feat(rendering): add default checkerboard texture --- src/main.rs | 52 ++++++++++++++++++++++++++++++++---------------- src/model/mod.rs | 2 +- src/texture.rs | 21 +++++++++++++++++++ 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index 54e5339..b424169 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,13 @@ use bytemuck::bytes_of; -use image::EncodableLayout; use std::collections::BTreeMap; use std::io::BufReader; use std::sync::Arc; -use tobj::LoadOptions; +use std::time::Instant; use tracing::info; use wgpu::util::DeviceExt; -use wgpu::{Backends, BufferUsages, Device, FragmentState, IndexFormat, Instance, InstanceDescriptor, PipelineCompilationOptions}; +use wgpu::{ + Backends, FragmentState, IndexFormat, Instance, InstanceDescriptor, PipelineCompilationOptions, +}; use winit::application::ApplicationHandler; use winit::event::{ElementState, MouseButton}; use winit::event_loop::{ActiveEventLoop, EventLoop}; @@ -45,8 +46,9 @@ struct WgpuRenderer<'surface> { camera_buffer: wgpu::Buffer, camera_bind_group: wgpu::BindGroup, pumpkin: model::Model, - - zenyx_logo: wgpu::BindGroup, + delta: f32, + last_frame_time: Instant, + default_texture: wgpu::BindGroup, } impl WgpuRenderer<'_> { @@ -88,7 +90,7 @@ impl WgpuRenderer<'_> { .material .and_then(|i| self.pumpkin.materials.get(i)) .map(|m| &m.bind_group) - .unwrap_or(&self.zenyx_logo); + .unwrap_or(&self.default_texture); rpass.set_bind_group(1, bind_group, &[]); rpass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); rpass.set_index_buffer(mesh.index_buffer.slice(..), IndexFormat::Uint32); @@ -96,7 +98,11 @@ impl WgpuRenderer<'_> { } } self.queue.submit(Some(encoder.finish())); - surface_texture.present() + let delta_time = std::time::Instant::now() - self.last_frame_time; + self.delta = delta_time.as_secs_f32(); + info!("{}", self.delta); + surface_texture.present(); + self.last_frame_time = std::time::Instant::now(); } } @@ -134,8 +140,8 @@ struct WgpuState { instance: wgpu::Instance, } -static ICON: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/Badge.png")); -static PUMPKIN: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/Pumpkin.obj")); +static _ICON: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/Badge.png")); +static _PUMPKIN: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/Pumpkin.obj")); impl WgpuState { fn new() -> Self { @@ -303,24 +309,35 @@ impl WgpuState { &queue, &texture_bind_group_layout, ); + let checkerboard_img = crate::texture::create_checkerboard(); + let checkerboard_texture = + texture::Texture::from_image(&device, &queue, &checkerboard_img, Some("checkerboard")) + .unwrap(); - let zenyx_logo = texture::Texture::from_bytes(&device, &queue, ICON, "zenyx-icon").unwrap(); + let checkerboard_sampler = device.create_sampler(&wgpu::SamplerDescriptor { + address_mode_u: wgpu::AddressMode::Repeat, + address_mode_v: wgpu::AddressMode::Repeat, + address_mode_w: wgpu::AddressMode::Repeat, + mag_filter: wgpu::FilterMode::Nearest, + min_filter: wgpu::FilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, + ..Default::default() + }); - let zenyx_logo = device.create_bind_group(&wgpu::BindGroupDescriptor { - label: Some("zenyx-logo-diffuse"), + let default_texture = device.create_bind_group(&wgpu::BindGroupDescriptor { + label: Some("checkerboard-bind-group"), layout: &texture_bind_group_layout, entries: &[ wgpu::BindGroupEntry { binding: 0, - resource: wgpu::BindingResource::TextureView(&zenyx_logo.view), + resource: wgpu::BindingResource::TextureView(&checkerboard_texture.view), }, wgpu::BindGroupEntry { binding: 1, - resource: wgpu::BindingResource::Sampler(&zenyx_logo.sampler), + resource: wgpu::BindingResource::Sampler(&checkerboard_sampler), }, ], }); - let (depth_texture, depth_texture_view) = create_depth_texture(&device, surface_config.width, surface_config.height); let camera = camera::Camera { @@ -370,10 +387,11 @@ impl WgpuState { camera_bind_group, depth_texture_view, pumpkin, - zenyx_logo, + default_texture, + delta: 0f32, + last_frame_time: Instant::now(), } } - } fn create_depth_texture( diff --git a/src/model/mod.rs b/src/model/mod.rs index 1309cff..23bb69b 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -48,7 +48,7 @@ impl Model { let Some(texture) = &m.diffuse_texture else { continue; }; - let diffuse_texture = load_texture(&m.name, texture, device, queue); + let diffuse_texture = load_texture(&m.name, texture, device, queue); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: Some("model-texture-bind"), layout, diff --git a/src/texture.rs b/src/texture.rs index 42fda6e..f5aaab1 100644 --- a/src/texture.rs +++ b/src/texture.rs @@ -85,3 +85,24 @@ impl Texture { }) } } + +pub fn create_checkerboard() -> image::DynamicImage { + let size = 512; + let tile_size = 24; + let mut img = image::RgbaImage::new(size, size); + + for y in 0..size { + for x in 0..size { + let tile_x = x / tile_size; + let tile_y = y / tile_size; + let color = if (tile_x + tile_y) % 2 == 0 { + [0, 0, 0, 255] + } else { + [255, 5, 255, 255] + }; + img.put_pixel(x, y, image::Rgba(color)); + } + } + + image::DynamicImage::ImageRgba8(img) +}