feat(rendering): add default checkerboard texture

This commit is contained in:
Chance 2025-04-20 14:47:03 -04:00 committed by BitSyndicate
parent a71231a3a0
commit e32e764315
Signed by: bitsyndicate
GPG key ID: 443E4198D6BBA6DE
3 changed files with 57 additions and 18 deletions

View file

@ -1,12 +1,13 @@
use bytemuck::bytes_of; use bytemuck::bytes_of;
use image::EncodableLayout;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::io::BufReader; use std::io::BufReader;
use std::sync::Arc; use std::sync::Arc;
use tobj::LoadOptions; use std::time::Instant;
use tracing::info; use tracing::info;
use wgpu::util::DeviceExt; 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::application::ApplicationHandler;
use winit::event::{ElementState, MouseButton}; use winit::event::{ElementState, MouseButton};
use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::event_loop::{ActiveEventLoop, EventLoop};
@ -45,8 +46,9 @@ struct WgpuRenderer<'surface> {
camera_buffer: wgpu::Buffer, camera_buffer: wgpu::Buffer,
camera_bind_group: wgpu::BindGroup, camera_bind_group: wgpu::BindGroup,
pumpkin: model::Model, pumpkin: model::Model,
delta: f32,
zenyx_logo: wgpu::BindGroup, last_frame_time: Instant,
default_texture: wgpu::BindGroup,
} }
impl WgpuRenderer<'_> { impl WgpuRenderer<'_> {
@ -88,7 +90,7 @@ impl WgpuRenderer<'_> {
.material .material
.and_then(|i| self.pumpkin.materials.get(i)) .and_then(|i| self.pumpkin.materials.get(i))
.map(|m| &m.bind_group) .map(|m| &m.bind_group)
.unwrap_or(&self.zenyx_logo); .unwrap_or(&self.default_texture);
rpass.set_bind_group(1, bind_group, &[]); rpass.set_bind_group(1, bind_group, &[]);
rpass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); rpass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
rpass.set_index_buffer(mesh.index_buffer.slice(..), IndexFormat::Uint32); rpass.set_index_buffer(mesh.index_buffer.slice(..), IndexFormat::Uint32);
@ -96,7 +98,11 @@ impl WgpuRenderer<'_> {
} }
} }
self.queue.submit(Some(encoder.finish())); 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, instance: wgpu::Instance,
} }
static ICON: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/Badge.png")); 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 _PUMPKIN: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/Pumpkin.obj"));
impl WgpuState { impl WgpuState {
fn new() -> Self { fn new() -> Self {
@ -303,24 +309,35 @@ impl WgpuState {
&queue, &queue,
&texture_bind_group_layout, &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 { let default_texture = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("zenyx-logo-diffuse"), label: Some("checkerboard-bind-group"),
layout: &texture_bind_group_layout, layout: &texture_bind_group_layout,
entries: &[ entries: &[
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 0, binding: 0,
resource: wgpu::BindingResource::TextureView(&zenyx_logo.view), resource: wgpu::BindingResource::TextureView(&checkerboard_texture.view),
}, },
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 1, binding: 1,
resource: wgpu::BindingResource::Sampler(&zenyx_logo.sampler), resource: wgpu::BindingResource::Sampler(&checkerboard_sampler),
}, },
], ],
}); });
let (depth_texture, depth_texture_view) = let (depth_texture, depth_texture_view) =
create_depth_texture(&device, surface_config.width, surface_config.height); create_depth_texture(&device, surface_config.width, surface_config.height);
let camera = camera::Camera { let camera = camera::Camera {
@ -370,10 +387,11 @@ impl WgpuState {
camera_bind_group, camera_bind_group,
depth_texture_view, depth_texture_view,
pumpkin, pumpkin,
zenyx_logo, default_texture,
delta: 0f32,
last_frame_time: Instant::now(),
} }
} }
} }
fn create_depth_texture( fn create_depth_texture(

View file

@ -48,7 +48,7 @@ impl Model {
let Some(texture) = &m.diffuse_texture else { let Some(texture) = &m.diffuse_texture else {
continue; 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 { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("model-texture-bind"), label: Some("model-texture-bind"),
layout, layout,

View file

@ -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)
}