material.rs (4350B)
1 use crate::GpuData; 2 use crate::texture::{make_1x1_rgba8, texture_layout_entry}; 3 use glam::Vec4; 4 5 #[repr(C)] 6 #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] 7 pub struct MaterialUniform { 8 pub base_color_factor: glam::Vec4, // rgba 9 pub metallic_factor: f32, 10 pub roughness_factor: f32, 11 pub ao_strength: f32, 12 pub _pad0: f32, 13 } 14 15 pub struct MaterialGpu { 16 pub _uniform: MaterialUniform, 17 pub _buffer: wgpu::Buffer, 18 pub bindgroup: wgpu::BindGroup, 19 } 20 21 pub fn make_material_gpudata( 22 device: &wgpu::Device, 23 queue: &wgpu::Queue, 24 ) -> (GpuData<MaterialUniform>, wgpu::BindGroupLayout) { 25 let material_uniform = MaterialUniform { 26 base_color_factor: Vec4::new(1.0, 0.1, 0.1, 1.0), 27 metallic_factor: 1.0, 28 roughness_factor: 0.1, 29 ao_strength: 1.0, 30 _pad0: 0.0, 31 }; 32 33 let material_buf = device.create_buffer(&wgpu::BufferDescriptor { 34 label: Some("material"), 35 size: std::mem::size_of::<MaterialUniform>() as u64, 36 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 37 mapped_at_creation: false, 38 }); 39 40 let material_sampler = device.create_sampler(&wgpu::SamplerDescriptor { 41 label: Some("material_sampler"), 42 address_mode_u: wgpu::AddressMode::Repeat, 43 address_mode_v: wgpu::AddressMode::Repeat, 44 address_mode_w: wgpu::AddressMode::Repeat, 45 mag_filter: wgpu::FilterMode::Linear, 46 min_filter: wgpu::FilterMode::Linear, 47 mipmap_filter: wgpu::FilterMode::Linear, 48 ..Default::default() 49 }); 50 51 // Default textures 52 let basecolor_view = make_1x1_rgba8( 53 device, 54 queue, 55 wgpu::TextureFormat::Rgba8UnormSrgb, 56 [255, 255, 255, 255], 57 "basecolor_1x1", 58 ); 59 60 let mr_view = make_1x1_rgba8( 61 device, 62 queue, 63 wgpu::TextureFormat::Rgba8Unorm, 64 [0, 255, 0, 255], // G=roughness=1, B=metallic=0 (A unused) 65 "mr_1x1", 66 ); 67 68 let normal_view = make_1x1_rgba8( 69 device, 70 queue, 71 wgpu::TextureFormat::Rgba8Unorm, 72 [128, 128, 255, 255], 73 "normal_1x1", 74 ); 75 76 let material_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 77 label: Some("material_bgl"), 78 entries: &[ 79 // uniform 80 wgpu::BindGroupLayoutEntry { 81 binding: 0, 82 visibility: wgpu::ShaderStages::FRAGMENT, 83 ty: wgpu::BindingType::Buffer { 84 ty: wgpu::BufferBindingType::Uniform, 85 has_dynamic_offset: false, 86 min_binding_size: None, 87 }, 88 count: None, 89 }, 90 // sampler 91 wgpu::BindGroupLayoutEntry { 92 binding: 1, 93 visibility: wgpu::ShaderStages::FRAGMENT, 94 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), 95 count: None, 96 }, 97 // baseColor (sRGB) 98 texture_layout_entry(2), 99 // metallicRougness (linear) 100 texture_layout_entry(3), 101 // normal (linear) 102 texture_layout_entry(4), 103 ], 104 }); 105 106 let material_bg = device.create_bind_group(&wgpu::BindGroupDescriptor { 107 label: Some("material_bg"), 108 layout: &material_bgl, 109 entries: &[ 110 wgpu::BindGroupEntry { 111 binding: 0, 112 resource: material_buf.as_entire_binding(), 113 }, 114 wgpu::BindGroupEntry { 115 binding: 1, 116 resource: wgpu::BindingResource::Sampler(&material_sampler), 117 }, 118 wgpu::BindGroupEntry { 119 binding: 2, 120 resource: wgpu::BindingResource::TextureView(&basecolor_view), 121 }, 122 wgpu::BindGroupEntry { 123 binding: 3, 124 resource: wgpu::BindingResource::TextureView(&mr_view), 125 }, 126 wgpu::BindGroupEntry { 127 binding: 4, 128 resource: wgpu::BindingResource::TextureView(&normal_view), 129 }, 130 ], 131 }); 132 133 ( 134 GpuData::<MaterialUniform> { 135 data: material_uniform, 136 buffer: material_buf, 137 bindgroup: material_bg, 138 }, 139 material_bgl, 140 ) 141 }