use crate::core::input::InputManager; use crate::core::render::pipelines::triangle_pipeline::create_triangle_pipeline; use crate::core::render::primitives::camera::Camera; use crate::core::render::primitives::vertex::Vertex2D; use crate::core::render::render_context::RenderContext; use crate::core::render::texture::Texture; use crate::core::scene::Scene; use crate::core::timer::Timer; use glam::{Mat4, Vec3}; use std::sync::Arc; use vulkano::buffer::Subbuffer; use vulkano::command_buffer::{ AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, PrimaryCommandBufferAbstract, }; use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet}; use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint}; const VERTICES: [Vertex2D; 4] = [ Vertex2D { position: [0.0, 0.0], uv: [0.0, 0.0], }, Vertex2D { position: [0.0, 5.0], uv: [0.0, 0.5], }, Vertex2D { position: [10.0, 0.0], uv: [1.0, 0.0], }, Vertex2D { position: [10.0, 5.0], uv: [1.0, 0.5], }, ]; pub struct MainSceneState { pipeline: Arc, vertex_buffer: Subbuffer<[Vertex2D]>, camera: Camera, texture: Texture, speed: f32, } #[derive(Default)] pub struct MainScene { state: Option, } impl Scene for MainScene { fn loaded(&self) -> bool { self.state.is_some() } fn load(&mut self, render_context: &RenderContext) { let pipeline = create_triangle_pipeline(render_context.device(), render_context.swapchain_format()) .unwrap(); let vertex_buffer = Vertex2D::create_buffer(Vec::from_iter(VERTICES), render_context.memory_allocator()) .unwrap(); let mut camera = Camera::new( Mat4::look_at_rh( Vec3::new(0.3, 0.3, 1.0), Vec3::new(0.0, 0.0, 0.0), Vec3::new(0.0, -1.0, 0.0), ), Mat4::perspective_rh_gl( std::f32::consts::FRAC_PI_2, render_context.aspect_ratio(), 0.01, 100.0, ), ); camera.set_position(Vec3::new(-10.0, 0.0, -10.0)); let mut uploads = AutoCommandBufferBuilder::primary( render_context.command_buffer_allocator().clone(), render_context.graphics_queue().queue_family_index(), CommandBufferUsage::OneTimeSubmit, ) .unwrap(); let texture = Texture::from_file( render_context.device(), render_context.memory_allocator(), &mut uploads, "res/textures/wooden-crate.jpg", ) .unwrap(); let _ = uploads .build() .unwrap() .execute(render_context.graphics_queue().clone()) .unwrap(); self.state = Some(MainSceneState { pipeline, vertex_buffer, camera, texture, speed: 50.0, }); } fn update( &mut self, render_context: &RenderContext, input_manager: &InputManager, timer: &Timer, ) { let state = self.state.as_mut().unwrap(); state.speed += input_manager.get_virtual_input_state("mouse_wheel") * 10.0; let speed = state.speed * timer.delta_time(); state.camera.rotate(Vec3::new( (input_manager.get_virtual_input_state("mouse_y") * 50.0 * timer.delta_time()) .to_radians(), (input_manager.get_virtual_input_state("mouse_x") * 50.0 * timer.delta_time()) .to_radians(), 0.0, )); if state.camera.get_rotation().x > 89.0 { state .camera .set_rotation(Vec3::new(89.0, state.camera.get_rotation().y, 0.0)); } if state.camera.get_rotation().x < -89.0 { state .camera .set_rotation(Vec3::new(-89.0, state.camera.get_rotation().y, 0.0)); } let rotation = state.camera.get_rotation(); let mut translation = Vec3::ZERO; let tx = input_manager.get_virtual_input_state("move_right") * timer.delta_time() * speed; translation.x += tx * (rotation.y).to_radians().cos(); translation.z += tx * (rotation.y).to_radians().sin(); let ty = input_manager.get_virtual_input_state("move_forward") * timer.delta_time() * speed; translation.x += ty * (rotation.y + 90.0).to_radians().cos(); translation.z += ty * (rotation.y + 90.0).to_radians().sin(); state.camera.translate(translation); state.camera.set_projection(Mat4::perspective_rh_gl( std::f32::consts::FRAC_PI_2, render_context.aspect_ratio(), 0.01, 100.0, )); } fn render( &self, render_context: &RenderContext, builder: &mut AutoCommandBufferBuilder, ) { let state = self.state.as_ref().unwrap(); let vertex_count = state.vertex_buffer.len() as u32; let instance_count = vertex_count / 4; let layouts = state.pipeline.layout().set_layouts(); let uniform_buffer = state .camera .create_buffer(render_context.memory_allocator()) .unwrap(); let uniform_descriptor_set = DescriptorSet::new( render_context.descriptor_set_allocator().clone(), layouts[0].clone(), [WriteDescriptorSet::buffer(0, uniform_buffer)], [], ) .unwrap(); let texture_descriptor_set = DescriptorSet::new( render_context.descriptor_set_allocator().clone(), layouts[1].clone(), [ WriteDescriptorSet::sampler(0, state.texture.get_sampler().clone()), WriteDescriptorSet::image_view(1, state.texture.get_texture().clone()), ], [], ) .unwrap(); unsafe { builder .bind_pipeline_graphics(state.pipeline.clone()) .unwrap() .bind_descriptor_sets( PipelineBindPoint::Graphics, state.pipeline.layout().clone(), 0, vec![uniform_descriptor_set, texture_descriptor_set], ) .unwrap() .bind_vertex_buffers(0, state.vertex_buffer.clone()) .unwrap() .draw(vertex_count, instance_count, 0, 0) .unwrap(); } } fn unload(&mut self) {} }