diff --git a/.vscode/launch.json b/.vscode/launch.json index 521ee82..cdff0ce 100755 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,20 +7,20 @@ { "type": "lldb", "request": "launch", - "name": "Debug executable 'lyra-engine'", + "name": "Debug lyra testbed", "cargo": { "args": [ "build", - "--bin=lyra-engine", - "--package=lyra-engine" + "--manifest-path", "${workspaceFolder}/examples/testbed/Cargo.toml" + //"--bin=testbed", ], "filter": { - "name": "lyra-engine", + "name": "testbed", "kind": "bin" } }, "args": [], - "cwd": "${workspaceFolder}" + "cwd": "${workspaceFolder}/examples/testbed" }, { "type": "lldb", diff --git a/Cargo.lock b/Cargo.lock index 179240b..1ff9632 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1304,6 +1304,7 @@ dependencies = [ "image", "percent-encoding", "thiserror", + "tracing", "uuid", ] diff --git a/examples/testbed/Cargo.lock b/examples/testbed/Cargo.lock index 62ccafd..16d56f0 100644 --- a/examples/testbed/Cargo.lock +++ b/examples/testbed/Cargo.lock @@ -1343,6 +1343,7 @@ dependencies = [ "image", "percent-encoding", "thiserror", + "tracing", "uuid", ] diff --git a/examples/testbed/src/main.rs b/examples/testbed/src/main.rs index 9a639ac..f845d71 100644 --- a/examples/testbed/src/main.rs +++ b/examples/testbed/src/main.rs @@ -6,13 +6,13 @@ use lyra_engine::assets::{ResourceManager, Texture, Model}; use tracing::debug; -pub const VERTICES: &[Vertex] = &[ +/* pub const VERTICES: &[Vertex] = &[ Vertex { position: [-0.0868241, 0.49240386, 0.0], tex_coords: [0.4131759, 0.00759614], }, // A Vertex { position: [-0.49513406, 0.06958647, 0.0], tex_coords: [0.0048659444, 0.43041354], }, // B Vertex { position: [-0.21918549, -0.44939706, 0.0], tex_coords: [0.28081453, 0.949397], }, // C Vertex { position: [0.35966998, -0.3473291, 0.0], tex_coords: [0.85967, 0.84732914], }, // D Vertex { position: [0.44147372, 0.2347359, 0.0], tex_coords: [0.9414737, 0.2652641], }, // E -]; +]; */ pub const INDICES: &[u16] = &[ 0, 1, 4, @@ -67,11 +67,11 @@ impl Point3d { #[async_std::main] async fn main() { let setup_sys = |world: &mut World| -> anyhow::Result<()> { - { + /* { let mut window_options = world.get_resource_mut::>().unwrap(); window_options.cursor_grab = CursorGrabMode::Confined; window_options.cursor_visible = false; - } + } */ let mut resman = world.get_resource_mut::().unwrap(); let diffuse_texture = resman.request::("assets/happy-tree.png").unwrap(); @@ -102,11 +102,11 @@ async fn main() { world.spawn(( ModelComponent(cube_model), - TransformComponent::from(Transform::from_xyz(0.005, 0.5, -1.2)), + TransformComponent::from(Transform::from_xyz(0.005, 0.5, -2.2)), )); let mut camera = CameraComponent::new_3d(); - camera.transform.translation += math::Vec3::new(0.0, 0.0, 2.0); + camera.transform.translation += math::Vec3::new(0.0, 0.0, 7.5); //camera.transform.rotate_y(Angle::Degrees(-25.0)); camera.transform.rotate_z(math::Angle::Degrees(-90.0)); world.spawn((camera,)); @@ -140,10 +140,14 @@ async fn main() { let keys: Ref> = keys.unwrap(); let speed = 0.001; + let rot_speed = 1.0; let mut dir_x = 0.0; let mut dir_y = 0.0; + let mut rot_x = 0.0; + let mut rot_y = 0.0; + if keys.is_pressed(KeyCode::A) { dir_x += speed; } @@ -160,9 +164,25 @@ async fn main() { dir_y -= speed; } + if keys.is_pressed(KeyCode::Left) { + rot_y -= rot_speed; + } + + if keys.is_pressed(KeyCode::Right) { + rot_y += rot_speed; + } + + if keys.is_pressed(KeyCode::Up) { + rot_x -= rot_speed; + } + + if keys.is_pressed(KeyCode::Down) { + rot_x += rot_speed; + } + drop(keys); - if dir_x == 0.0 && dir_y == 0.0 { + if dir_x == 0.0 && dir_y == 0.0 && rot_x == 0.0 && rot_y == 0.0 { return Ok(()); } @@ -170,12 +190,15 @@ async fn main() { for transform in world.query_mut::<(&mut TransformComponent,)>().iter_mut() { let t = &mut transform.transform; - debug!("Translation: {}", t.translation); + //debug!("Translation: {}", t.translation); + //debug!("Rotation: {}", t.rotation); /* t.translation += glam::Vec3::new(0.0, 0.001, 0.0); t.translation.x *= -1.0; */ t.translation.x += dir_x; t.translation.y += dir_y; + t.rotate_x(math::Angle::Degrees(rot_x)); + t.rotate_y(math::Angle::Degrees(rot_y)); } let events = world.get_resource_mut::().unwrap(); diff --git a/lyra-resource/Cargo.toml b/lyra-resource/Cargo.toml index f5a7799..1dda54f 100644 --- a/lyra-resource/Cargo.toml +++ b/lyra-resource/Cargo.toml @@ -14,4 +14,5 @@ gltf = { version = "1.3.0", features = ["KHR_materials_pbrSpecularGlossiness"] } image = "0.24.7" percent-encoding = "2.3.0" thiserror = "1.0.48" +tracing = "0.1.37" uuid = { version = "1.4.1", features = ["v4"] } diff --git a/lyra-resource/src/loader/model.rs b/lyra-resource/src/loader/model.rs index 3b878f2..731e115 100644 --- a/lyra-resource/src/loader/model.rs +++ b/lyra-resource/src/loader/model.rs @@ -4,6 +4,8 @@ use base64::Engine; use crate::{ResourceLoader, LoaderError, Mesh, Model, MeshVertexAttribute, VertexAttributeData, Resource, Material, ResHandle}; +use tracing::debug; + impl From for LoaderError { fn from(value: gltf::Error) -> Self { LoaderError::DecodingError(value.into()) @@ -40,6 +42,7 @@ impl ModelLoader { // read the positions if let Some(pos) = reader.read_positions() { + debug!("Mesh mode is {:?}", prim.mode()); let pos: Vec = pos.map(|t| t.into()).collect(); new_mesh.add_attribute(MeshVertexAttribute::Position, VertexAttributeData::Vec3(pos)); } diff --git a/src/render/default_texture.png b/src/render/default_texture.png new file mode 100644 index 0000000..ec02f5b Binary files /dev/null and b/src/render/default_texture.png differ diff --git a/src/render/renderer.rs b/src/render/renderer.rs index ab01d2f..0478f5d 100755 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -40,7 +40,6 @@ struct RenderBufferStorage { render_texture: Option, texture_bindgroup: Option, - texture_layout: Option, /// The index of the transform for this entity. /// The tuple is structured like this: (transform index, index of transform inside the buffer) @@ -155,6 +154,8 @@ pub struct BasicRenderer { camera_buffer: wgpu::Buffer, camera_bind_group: wgpu::BindGroup, + texture_bind_group_layout: BindGroupLayout, + default_texture_bind_group: BindGroup, depth_buffer_texture: RenderTexture, } @@ -343,12 +344,27 @@ impl BasicRenderer { let depth_texture = RenderTexture::create_depth_texture(&device, &config, "Depth Buffer"); - let mut pipelines = HashMap::new(); - pipelines.insert(0, Arc::new(FullRenderPipeline::new(&device, &config, &shader, - vec![super::vertex::Vertex::desc(),], - vec![&texture_bind_group_layout, &transform_bind_group_layout, &camera_bind_group_layout]))); + // load the default texture + let bytes = include_bytes!("default_texture.png"); + let tex = RenderTexture::from_bytes(&device, &queue, bytes, "default_texture").unwrap(); + let default_tex_bindgroup = device.create_bind_group( + &wgpu::BindGroupDescriptor { + layout: &texture_bind_group_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::TextureView(tex.view()), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::Sampler(tex.sampler()), + } + ], + label: Some("default_texture"), + } + ); - Self { + let mut s = Self { window, surface, device, @@ -361,7 +377,7 @@ impl BasicRenderer { b: 0.3, a: 1.0, }, - render_pipelines: pipelines, + render_pipelines: HashMap::new(), render_jobs: VecDeque::new(), buffer_storage: HashMap::new(), @@ -373,8 +389,19 @@ impl BasicRenderer { camera_buffer, camera_bind_group, + texture_bind_group_layout, + default_texture_bind_group: default_tex_bindgroup, depth_buffer_texture: depth_texture, - } + }; + + // create the default pipelines + let mut pipelines = HashMap::new(); + pipelines.insert(0, Arc::new(FullRenderPipeline::new(&s.device, &s.config, &shader, + vec![super::vertex::Vertex::desc(),], + vec![&s.texture_bind_group_layout, &s.transform_bind_group_layout, &camera_bind_group_layout]))); + s.render_pipelines = pipelines; + + s } fn find_next_multiple(n: u32, mul: u32) -> u32 { @@ -385,13 +412,13 @@ impl BasicRenderer { } } - // TODO: minimize how often model buffers are updated by checking if they changed fn update_mesh_buffers(&mut self, entity: EntityId, mesh: &Mesh) { if let Some(buffers) = self.buffer_storage.get_mut(&entity) { // check if the buffer sizes dont match. If they dont, completely remake the buffers let vertices = mesh.position().unwrap(); if buffers.buffer_vertex.count() != vertices.len() { drop(buffers); + debug!("Recreating buffers for mesh"); let (vert, idx) = self.create_vertex_index_buffers(mesh); // have to re-get buffers because of borrow checker @@ -456,38 +483,13 @@ impl BasicRenderer { fn create_mesh_buffers(&mut self, mesh: &Mesh, transform_indices: TransformBufferIndices) -> RenderBufferStorage { let (vertex_buffer, buffer_indices) = self.create_vertex_index_buffers(mesh); - let (diffuse_layout, diffuse_bindgroup) = if let Some(model_texture) = &mesh.material().texture { + let diffuse_bindgroup = if let Some(model_texture) = &mesh.material().texture { let image = &model_texture.data.as_ref().unwrap().image; let diffuse_texture = RenderTexture::from_image(&self.device, &self.queue, image, None).unwrap(); - let texture_bind_group_layout = - self.device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - // This should match the filterable field of the - // corresponding Texture entry above. - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - label: Some("texture_bind_group_layout"), - }); - let diffuse_bind_group = self.device.create_bind_group( &wgpu::BindGroupDescriptor { - layout: &texture_bind_group_layout, + layout: &self.texture_bind_group_layout, entries: &[ wgpu::BindGroupEntry { binding: 0, @@ -502,16 +504,15 @@ impl BasicRenderer { } ); - (Some(texture_bind_group_layout), Some(diffuse_bind_group)) + Some(diffuse_bind_group) } else { - (None, None) + None }; RenderBufferStorage { buffer_vertex: vertex_buffer, buffer_indices, render_texture: None, - texture_layout: diffuse_layout, texture_bindgroup: diffuse_bindgroup, transform_index: transform_indices } @@ -561,7 +562,6 @@ impl Renderer for BasicRenderer { let mut alive_entities = HashSet::new(); for (entity, model, model_epoch, transform) in main_world.query::<(Entities, &ModelComponent, EpochOf, &TransformComponent)>().iter() { - debug!("Collecting model things"); let model = model.data.as_ref().unwrap().as_ref(); let model_mesh = model.meshes.first().unwrap(); @@ -649,8 +649,6 @@ impl Renderer for BasicRenderer { }), }); - debug!("Executing {} render jobs", self.render_jobs.len()); - // Pop off jobs from the queue as they're being processed while let Some(job) = self.render_jobs.pop_front() { if let Some(pipeline) = self.render_pipelines.get(&job.mesh().material().shader_uuid.unwrap_or(0)) { @@ -664,6 +662,8 @@ impl Renderer for BasicRenderer { // Bind the optional texture if let Some(tex) = buffers.texture_bindgroup.as_ref() { render_pass.set_bind_group(0, &tex, &[]); + } else { + render_pass.set_bind_group(0, &self.default_texture_bind_group, &[]); } // Get the bindgroup for job's transform and bind to it using an offset. @@ -680,7 +680,7 @@ impl Renderer for BasicRenderer { let indices_len = indices.count() as u32; render_pass.set_vertex_buffer(buffers.buffer_vertex.slot(), buffers.buffer_vertex.buffer().slice(..)); - render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint16); + render_pass.set_index_buffer(indices.buffer().slice(..), wgpu::IndexFormat::Uint32); render_pass.draw_indexed(0..indices_len, 0, 0..1); } else { let vertices = mesh.position().unwrap(); diff --git a/src/render/shaders/base.wgsl b/src/render/shaders/base.wgsl index c8e6ce1..6361232 100755 --- a/src/render/shaders/base.wgsl +++ b/src/render/shaders/base.wgsl @@ -2,7 +2,7 @@ struct VertexInput { @location(0) position: vec3, - @location(1) tex_coords: vec2, + //@location(1) tex_coords: vec2, } struct VertexOutput { @@ -25,7 +25,7 @@ fn vs_main( model: VertexInput, ) -> VertexOutput { var out: VertexOutput; - out.tex_coords = model.tex_coords; + out.tex_coords = vec2(1.0, 1.0); out.clip_position = camera.view_proj * u_model_transform * vec4(model.position, 1.0); return out; } diff --git a/src/render/vertex.rs b/src/render/vertex.rs index 12ac319..0f18f77 100755 --- a/src/render/vertex.rs +++ b/src/render/vertex.rs @@ -1,3 +1,5 @@ +use glam::Vec3; + use super::desc_buf_lay::DescVertexBufferLayout; #[repr(C)] @@ -5,13 +7,13 @@ use super::desc_buf_lay::DescVertexBufferLayout; pub struct Vertex { pub position: [f32; 3], //pub color: [f32; 3], // TODO: add color again - pub tex_coords: [f32; 2] + //pub tex_coords: [f32; 2] } impl DescVertexBufferLayout for Vertex { fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, + array_stride: std::mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, attributes: &[ wgpu::VertexAttribute { @@ -19,11 +21,11 @@ impl DescVertexBufferLayout for Vertex { shader_location: 0, format: wgpu::VertexFormat::Float32x3, }, - wgpu::VertexAttribute { + /* wgpu::VertexAttribute { offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress, shader_location: 1, format: wgpu::VertexFormat::Float32x2, - } + } */ ] } }