| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927 |
- use rand::Rng;
- use std::iter;
- use cgmath::prelude::*;
- use wgpu::util::DeviceExt;
- use winit::{
- event::*,
- event_loop::{ControlFlow, EventLoop},
- window::Window,
- };
- use drk::gfx::{camera, model, texture};
- use model::{DrawModel, Vertex};
- use std::time::Instant;
- #[macro_use]
- extern crate lazy_static;
- lazy_static! {
- static ref START: Instant = Instant::now();
- }
- fn get_time() -> f32 {
- START.elapsed().as_secs_f32()
- }
- const FONT_BYTES: &[u8] = include_bytes!("../../res/font/PressStart2P-Regular.ttf");
- const NUM_INSTANCES_PER_ROW: u32 = 10;
- #[repr(C)]
- #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
- struct Uniforms {
- view_position: [f32; 4],
- view_proj: [[f32; 4]; 4],
- }
- impl Uniforms {
- fn new() -> Self {
- Self {
- view_position: [0.0; 4],
- view_proj: cgmath::Matrix4::identity().into(),
- }
- }
- fn update_view_proj(&mut self, camera: &camera::Camera, projection: &camera::Projection) {
- self.view_position = camera.position.to_homogeneous().into();
- self.view_proj = (projection.calc_matrix() * camera.calc_matrix()).into()
- }
- }
- struct Instance {
- position: cgmath::Vector3<f32>,
- rotation: cgmath::Quaternion<f32>,
- }
- impl Instance {
- fn to_raw(&self) -> InstanceRaw {
- InstanceRaw {
- model: (cgmath::Matrix4::from_translation(self.position)
- * cgmath::Matrix4::from(self.rotation))
- .into(),
- }
- }
- }
- #[repr(C)]
- #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
- struct InstanceRaw {
- #[allow(dead_code)]
- model: [[f32; 4]; 4],
- }
- impl model::Vertex for InstanceRaw {
- fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
- use std::mem;
- wgpu::VertexBufferLayout {
- array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
- // We need to switch from using a step mode of Vertex to Instance
- // This means that our shaders will only change to use the next
- // instance when the shader starts processing a new instance
- step_mode: wgpu::InputStepMode::Instance,
- attributes: &[
- wgpu::VertexAttribute {
- offset: 0,
- // While our vertex shader only uses locations 0, and 1 now, in later tutorials
- // we'll be using 2, 3, and 4, for Vertex. We'll start at
- // slot 5 not conflict with them later
- shader_location: 5,
- format: wgpu::VertexFormat::Float4,
- },
- // A mat4 takes up 4 vertex slots as it is technically 4 vec4s. We need to define a
- // slot for each vec4. We don't have to do this in code though.
- wgpu::VertexAttribute {
- offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
- shader_location: 6,
- format: wgpu::VertexFormat::Float4,
- },
- wgpu::VertexAttribute {
- offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
- shader_location: 7,
- format: wgpu::VertexFormat::Float4,
- },
- wgpu::VertexAttribute {
- offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
- shader_location: 8,
- format: wgpu::VertexFormat::Float4,
- },
- ],
- }
- }
- }
- #[repr(C)]
- #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
- struct Light {
- position: [f32; 3],
- // Due to uniforms requiring 16 byte (4 float) spacing, we need to use a padding field here
- _padding: u32,
- color: [f32; 3],
- }
- pub const UNBOUNDED_F32: f32 = std::f32::INFINITY;
- #[derive(Debug)]
- pub struct Text {
- pub position: cgmath::Vector2<f32>,
- pub bounds: cgmath::Vector2<f32>,
- pub color: cgmath::Vector4<f32>,
- pub text: String,
- pub size: f32,
- pub visible: bool,
- pub focused: bool,
- pub centered: bool,
- }
- impl Default for Text {
- fn default() -> Self {
- Self {
- position: (0.0, 0.0).into(),
- bounds: (UNBOUNDED_F32, UNBOUNDED_F32).into(),
- color: (1.0, 1.0, 1.0, 1.0).into(),
- text: String::new(),
- size: 16.0,
- visible: false,
- focused: false,
- centered: false,
- }
- }
- }
- const VERTEX_Z: f32 = 0.0;
- // (-1, 1) (1, 1)
- // +-----------------------+
- // | |
- // | |
- // | |
- // | |
- // | |
- // | |
- // | |
- // +-----------------------+
- // (-1, -1) (1, -1)
- const VERTICES: &[model::ModelVertex] = &[
- // top left
- model::ModelVertex {
- position: [-1.0, 1.0, VERTEX_Z],
- tex_coords: [0.0, 0.0],
- normal: [0.0, 0.0, -1.0],
- },
- // bottom left
- model::ModelVertex {
- position: [-1.0, 0.5, VERTEX_Z],
- tex_coords: [0.0, 1.0],
- normal: [0.0, 0.0, -1.0],
- },
- // bottom right
- model::ModelVertex {
- position: [-0.5, 0.5, VERTEX_Z],
- tex_coords: [1.0, 1.0],
- normal: [0.0, 0.0, -1.0],
- },
- // top right
- model::ModelVertex {
- position: [-0.5, 1.0, VERTEX_Z],
- tex_coords: [1.0, 0.0],
- normal: [0.0, 0.0, -1.0],
- },
- ];
- //const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4];
- const INDICES: &[u16] = &[0, 1, 2, 0, 2, 3];
- #[allow(dead_code)]
- struct State {
- surface: wgpu::Surface,
- device: wgpu::Device,
- queue: wgpu::Queue,
- sc_desc: wgpu::SwapChainDescriptor,
- swap_chain: wgpu::SwapChain,
- render_pipeline: wgpu::RenderPipeline,
- obj_model: model::Model,
- camera: camera::Camera, // UPDATED!
- projection: camera::Projection, // NEW!
- camera_controller: camera::CameraController, // UPDATED!
- uniforms: Uniforms,
- uniform_buffer: wgpu::Buffer,
- uniform_bind_group: wgpu::BindGroup,
- instances: Vec<Instance>,
- #[allow(dead_code)]
- instance_buffer: wgpu::Buffer,
- depth_texture: texture::Texture,
- size: winit::dpi::PhysicalSize<u32>,
- light: Light,
- light_buffer: wgpu::Buffer,
- light_bind_group: wgpu::BindGroup,
- light_render_pipeline: wgpu::RenderPipeline,
- ui_render_pipeline: wgpu::RenderPipeline,
- vertex_buffer: wgpu::Buffer,
- index_buffer: wgpu::Buffer,
- num_indices: u32,
- #[allow(dead_code)]
- diffuse_texture: texture::Texture,
- diffuse_bind_group: wgpu::BindGroup,
- #[allow(dead_code)]
- cartoon_texture: texture::Texture,
- cartoon_bind_group: wgpu::BindGroup,
- glyph_brush: wgpu_glyph::GlyphBrush<()>,
- staging_belt: wgpu::util::StagingBelt,
- is_space_pressed: bool,
- mouse_pressed: bool,
- }
- fn create_render_pipeline(
- device: &wgpu::Device,
- layout: &wgpu::PipelineLayout,
- color_format: wgpu::TextureFormat,
- depth_format: Option<wgpu::TextureFormat>,
- vertex_layouts: &[wgpu::VertexBufferLayout],
- vs_src: wgpu::ShaderModuleDescriptor,
- fs_src: wgpu::ShaderModuleDescriptor,
- ) -> wgpu::RenderPipeline {
- let vs_module = device.create_shader_module(&vs_src);
- let fs_module = device.create_shader_module(&fs_src);
- device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
- label: Some("Render Pipeline"),
- layout: Some(&layout),
- vertex: wgpu::VertexState {
- module: &vs_module,
- entry_point: "main",
- buffers: vertex_layouts,
- },
- fragment: Some(wgpu::FragmentState {
- module: &fs_module,
- entry_point: "main",
- targets: &[wgpu::ColorTargetState {
- format: color_format,
- alpha_blend: wgpu::BlendState::REPLACE,
- color_blend: wgpu::BlendState::REPLACE,
- write_mask: wgpu::ColorWrite::ALL,
- }],
- }),
- primitive: wgpu::PrimitiveState {
- topology: wgpu::PrimitiveTopology::TriangleList,
- strip_index_format: None,
- front_face: wgpu::FrontFace::Ccw,
- cull_mode: wgpu::CullMode::Back,
- // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
- polygon_mode: wgpu::PolygonMode::Fill,
- },
- depth_stencil: depth_format.map(|format| wgpu::DepthStencilState {
- format,
- depth_write_enabled: true,
- depth_compare: wgpu::CompareFunction::Less,
- stencil: wgpu::StencilState::default(),
- bias: wgpu::DepthBiasState::default(),
- // Setting this to true requires Features::DEPTH_CLAMPING
- clamp_depth: false,
- }),
- multisample: wgpu::MultisampleState {
- count: 1,
- mask: !0,
- alpha_to_coverage_enabled: false,
- },
- })
- }
- impl State {
- async fn new(window: &Window) -> Self {
- let size = window.inner_size();
- // The instance is a handle to our GPU
- // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
- let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
- let surface = unsafe { instance.create_surface(window) };
- let adapter = instance
- .request_adapter(&wgpu::RequestAdapterOptions {
- power_preference: wgpu::PowerPreference::default(),
- compatible_surface: Some(&surface),
- })
- .await
- .unwrap();
- let (device, queue) = adapter
- .request_device(
- &wgpu::DeviceDescriptor {
- label: None,
- features: wgpu::Features::empty(),
- limits: wgpu::Limits::default(),
- },
- None, // Trace path
- )
- .await
- .unwrap();
- let sc_desc = wgpu::SwapChainDescriptor {
- usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
- format: adapter.get_swap_chain_preferred_format(&surface),
- width: size.width,
- height: size.height,
- present_mode: wgpu::PresentMode::Fifo,
- };
- let swap_chain = device.create_swap_chain(&surface, &sc_desc);
- let texture_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- entries: &[
- wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Texture {
- multisampled: false,
- view_dimension: wgpu::TextureViewDimension::D2,
- sample_type: wgpu::TextureSampleType::Float { filterable: false },
- },
- count: None,
- },
- wgpu::BindGroupLayoutEntry {
- binding: 1,
- visibility: wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Sampler {
- comparison: false,
- filtering: true,
- },
- count: None,
- },
- ],
- label: Some("texture_bind_group_layout"),
- });
- let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
- let projection =
- camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
- let camera_controller = camera::CameraController::new(4.0, 0.4);
- let mut uniforms = Uniforms::new();
- uniforms.update_view_proj(&camera, &projection);
- let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("Uniform Buffer"),
- contents: bytemuck::cast_slice(&[uniforms]),
- usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
- });
- const SPACE_BETWEEN: f32 = 3.0;
- let instances = (0..NUM_INSTANCES_PER_ROW)
- .flat_map(|z| {
- (0..NUM_INSTANCES_PER_ROW).map(move |x| {
- let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
- let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
- let y = 0.0;
- let position = cgmath::Vector3 { x, y, z };
- let rotation = cgmath::Quaternion::from_axis_angle(
- cgmath::Vector3::unit_z(),
- cgmath::Deg(180.0 + 0.0),
- );
- Instance { position, rotation }
- })
- })
- .collect::<Vec<_>>();
- let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
- let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("Instance Buffer"),
- contents: bytemuck::cast_slice(&instance_data),
- usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
- });
- let uniform_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- entries: &[wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- count: None,
- }],
- label: Some("uniform_bind_group_layout"),
- });
- let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- layout: &uniform_bind_group_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: uniform_buffer.as_entire_binding(),
- }],
- label: Some("uniform_bind_group"),
- });
- let res_dir = std::path::Path::new("res/model/");
- let obj_model = model::Model::load(
- &device,
- &queue,
- &texture_bind_group_layout,
- res_dir.join("earth.obj"),
- )
- .unwrap();
- let light = Light {
- position: [4.0, 4.0, 2.0],
- _padding: 0,
- color: [1.0, 1.0, 1.0],
- };
- let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("Light VB"),
- contents: bytemuck::cast_slice(&[light]),
- usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
- });
- let light_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- entries: &[wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Buffer {
- ty: wgpu::BufferBindingType::Uniform,
- has_dynamic_offset: false,
- min_binding_size: None,
- },
- count: None,
- }],
- label: None,
- });
- let light_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- layout: &light_bind_group_layout,
- entries: &[wgpu::BindGroupEntry {
- binding: 0,
- resource: light_buffer.as_entire_binding(),
- }],
- label: None,
- });
- let depth_texture =
- texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
- let render_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("Render Pipeline Layout"),
- bind_group_layouts: &[
- &texture_bind_group_layout,
- &uniform_bind_group_layout,
- &light_bind_group_layout,
- ],
- push_constant_ranges: &[],
- });
- let render_pipeline = create_render_pipeline(
- &device,
- &render_pipeline_layout,
- sc_desc.format,
- Some(texture::Texture::DEPTH_FORMAT),
- &[model::ModelVertex::desc(), InstanceRaw::desc()],
- wgpu::include_spirv!("../../res/shader/shader.vert.spv"),
- wgpu::include_spirv!("../../res/shader/shader.frag.spv"),
- );
- let light_render_pipeline = {
- let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("Light Pipeline Layout"),
- bind_group_layouts: &[&uniform_bind_group_layout, &light_bind_group_layout],
- push_constant_ranges: &[],
- });
- create_render_pipeline(
- &device,
- &layout,
- sc_desc.format,
- Some(texture::Texture::DEPTH_FORMAT),
- &[model::ModelVertex::desc()],
- wgpu::include_spirv!("../../res/shader/light.vert.spv"),
- wgpu::include_spirv!("../../res/shader/light.frag.spv"),
- )
- };
- //-------------------
- let texture_bind_group_layout =
- device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
- entries: &[
- wgpu::BindGroupLayoutEntry {
- binding: 0,
- visibility: wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Texture {
- multisampled: false,
- view_dimension: wgpu::TextureViewDimension::D2,
- sample_type: wgpu::TextureSampleType::Float { filterable: false },
- },
- count: None,
- },
- wgpu::BindGroupLayoutEntry {
- binding: 1,
- visibility: wgpu::ShaderStage::FRAGMENT,
- ty: wgpu::BindingType::Sampler {
- comparison: false,
- filtering: true,
- },
- count: None,
- },
- ],
- label: Some("texture_bind_group_layout"),
- });
- let diffuse_bytes = include_bytes!("../../res/img/absolutely-proprietary.png");
- let diffuse_texture =
- texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "stallman1").unwrap();
- let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- layout: &texture_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
- },
- ],
- label: Some("diffuse_bind_group"),
- });
- let cartoon_bytes = include_bytes!("../../res/img/absolutely-proprietary2.png");
- let cartoon_texture =
- texture::Texture::from_bytes(&device, &queue, cartoon_bytes, "stallman2").unwrap();
- let cartoon_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
- layout: &texture_bind_group_layout,
- entries: &[
- wgpu::BindGroupEntry {
- binding: 0,
- resource: wgpu::BindingResource::TextureView(&cartoon_texture.view),
- },
- wgpu::BindGroupEntry {
- binding: 1,
- resource: wgpu::BindingResource::Sampler(&cartoon_texture.sampler),
- },
- ],
- label: Some("cartoon_bind_group"),
- });
- let render_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: Some("Render Pipeline Layout"),
- bind_group_layouts: &[&texture_bind_group_layout],
- push_constant_ranges: &[],
- });
- let ui_render_pipeline = create_render_pipeline(
- &device,
- &render_pipeline_layout,
- sc_desc.format,
- Some(texture::Texture::DEPTH_FORMAT),
- &[model::ModelVertex::desc()],
- wgpu::include_spirv!("../../res/shader/ui_shader.vert.spv"),
- wgpu::include_spirv!("../../res/shader/ui_shader.frag.spv"),
- );
- let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("Vertex Buffer"),
- contents: bytemuck::cast_slice(VERTICES),
- usage: wgpu::BufferUsage::VERTEX,
- });
- let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
- label: Some("Index Buffer"),
- contents: bytemuck::cast_slice(INDICES),
- usage: wgpu::BufferUsage::INDEX,
- });
- let num_indices = INDICES.len() as u32;
- let font = wgpu_glyph::ab_glyph::FontArc::try_from_slice(FONT_BYTES).unwrap();
- let glyph_brush =
- wgpu_glyph::GlyphBrushBuilder::using_font(font).build(&device, sc_desc.format);
- let staging_belt = wgpu::util::StagingBelt::new(1024);
- Self {
- surface,
- device,
- queue,
- sc_desc,
- swap_chain,
- render_pipeline,
- obj_model,
- camera,
- projection,
- camera_controller,
- uniform_buffer,
- uniform_bind_group,
- uniforms,
- instances,
- instance_buffer,
- depth_texture,
- size,
- light,
- light_buffer,
- light_bind_group,
- light_render_pipeline,
- ui_render_pipeline,
- vertex_buffer,
- index_buffer,
- num_indices,
- diffuse_texture,
- diffuse_bind_group,
- cartoon_texture,
- cartoon_bind_group,
- glyph_brush,
- staging_belt,
- is_space_pressed: true,
- mouse_pressed: false,
- }
- }
- fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
- self.projection.resize(new_size.width, new_size.height);
- self.size = new_size;
- self.sc_desc.width = new_size.width;
- self.sc_desc.height = new_size.height;
- self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
- self.depth_texture =
- texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
- }
- fn input(&mut self, event: &DeviceEvent) -> bool {
- match event {
- DeviceEvent::Key(KeyboardInput {
- virtual_keycode: Some(key),
- state,
- ..
- }) => self.camera_controller.process_keyboard(*key, *state),
- DeviceEvent::MouseWheel { delta, .. } => {
- self.camera_controller.process_scroll(delta);
- true
- }
- DeviceEvent::Button {
- button: 1, // Left Mouse Button
- state,
- } => {
- self.mouse_pressed = *state == ElementState::Pressed;
- true
- }
- DeviceEvent::MouseMotion { delta } => {
- if self.mouse_pressed {
- self.camera_controller.process_mouse(delta.0, delta.1);
- }
- true
- }
- _ => false,
- }
- }
- fn update(&mut self, dt: std::time::Duration) {
- if rand::thread_rng().gen_range(0, 5) == 0 {
- self.is_space_pressed = !self.is_space_pressed;
- }
- self.camera_controller.update_camera(&mut self.camera, dt);
- self.uniforms
- .update_view_proj(&self.camera, &self.projection);
- self.queue.write_buffer(
- &self.uniform_buffer,
- 0,
- bytemuck::cast_slice(&[self.uniforms]),
- );
- let time = get_time();
- const SPACE_BETWEEN: f32 = 3.0;
- let instances = (0..NUM_INSTANCES_PER_ROW)
- .flat_map(|z| {
- (0..NUM_INSTANCES_PER_ROW).map(move |x| {
- let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
- let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
- //println!("{} {} {}", x, z, time);
- let y = ((x / 3.0 + time).sin() + (z / 3.0 + time).cos()) * 1.5;
- let position = cgmath::Vector3 { x, y, z };
- let rotation = cgmath::Quaternion::from_axis_angle(
- cgmath::Vector3::unit_z(),
- cgmath::Deg(180.0 + 0.0),
- );
- Instance { position, rotation }
- })
- })
- .collect::<Vec<_>>();
- let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
- self.queue.write_buffer(
- &self.instance_buffer,
- 0,
- bytemuck::cast_slice(&instance_data),
- );
- // Update the light
- let old_position: cgmath::Vector3<_> = self.light.position.into();
- self.light.position =
- (cgmath::Quaternion::from_axis_angle((0.0, 1.0, 0.0).into(), cgmath::Deg(1.0))
- * old_position)
- .into();
- self.queue
- .write_buffer(&self.light_buffer, 0, bytemuck::cast_slice(&[self.light]));
- }
- fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
- let frame = self.swap_chain.get_current_frame()?.output;
- let mut encoder = self
- .device
- .create_command_encoder(&wgpu::CommandEncoderDescriptor {
- label: Some("Render Encoder"),
- });
- {
- let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: Some("Render Pass"),
- color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
- attachment: &frame.view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear(wgpu::Color {
- r: 0.1,
- g: 0.2,
- b: 0.3,
- a: 1.0,
- }),
- store: true,
- },
- }],
- depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
- attachment: &self.depth_texture.view,
- depth_ops: Some(wgpu::Operations {
- load: wgpu::LoadOp::Clear(1.0),
- store: true,
- }),
- stencil_ops: None,
- }),
- });
- render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
- //render_pass.set_pipeline(&self.light_render_pipeline);
- //render_pass.draw_light_model(
- // &self.obj_model,
- // &self.uniform_bind_group,
- // &self.light_bind_group,
- //);
- render_pass.set_pipeline(&self.render_pipeline);
- render_pass.draw_model_instanced(
- &self.obj_model,
- 0..self.instances.len() as u32,
- &self.uniform_bind_group,
- &self.light_bind_group,
- );
- let bind_group = if self.is_space_pressed {
- &self.cartoon_bind_group
- } else {
- &self.diffuse_bind_group
- };
- render_pass.set_pipeline(&self.ui_render_pipeline);
- render_pass.set_bind_group(0, bind_group, &[]);
- render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
- render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
- render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
- }
- let play_text = Text {
- position: (40.0, 40.0).into(),
- color: (1.0, 1.0, 1.0, 1.0).into(),
- text: String::from("Absolutely Proprietary"),
- size: 32.0,
- centered: false,
- ..Default::default()
- };
- draw_text(&play_text, &mut self.glyph_brush);
- self.glyph_brush
- .draw_queued(
- &self.device,
- &mut self.staging_belt,
- &mut encoder,
- &frame.view,
- self.sc_desc.width,
- self.sc_desc.height,
- )
- .unwrap();
- self.staging_belt.finish();
- self.queue.submit(iter::once(encoder.finish()));
- Ok(())
- }
- }
- fn draw_text(text: &Text, glyph_brush: &mut wgpu_glyph::GlyphBrush<()>) {
- let layout = wgpu_glyph::Layout::default().h_align(if text.centered {
- wgpu_glyph::HorizontalAlign::Center
- } else {
- wgpu_glyph::HorizontalAlign::Left
- });
- let section = wgpu_glyph::Section {
- screen_position: text.position.into(),
- bounds: text.bounds.into(),
- layout,
- ..Default::default()
- }
- .add_text(
- wgpu_glyph::Text::new(&text.text)
- .with_color(text.color)
- .with_scale(if text.focused {
- text.size + 8.0
- } else {
- text.size
- }),
- );
- glyph_brush.queue(section);
- }
- fn main() {
- env_logger::init();
- let event_loop = EventLoop::new();
- let title = env!("CARGO_PKG_NAME");
- let window = winit::window::WindowBuilder::new()
- .with_title(title)
- .build(&event_loop)
- .unwrap();
- use futures::executor::block_on;
- let mut state = block_on(State::new(&window));
- let mut last_render_time = std::time::Instant::now();
- event_loop.run(move |event, _, control_flow| {
- *control_flow = ControlFlow::Poll;
- match event {
- Event::MainEventsCleared => window.request_redraw(),
- Event::DeviceEvent {
- ref event,
- .. // We're not using device_id currently
- } => {
- state.input(event);
- }
- Event::WindowEvent {
- ref event,
- window_id,
- } if window_id == window.id() => {
- match event {
- WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
- WindowEvent::KeyboardInput { input, .. } => match input {
- KeyboardInput {
- state: ElementState::Pressed,
- virtual_keycode: Some(VirtualKeyCode::Escape),
- ..
- } => {
- *control_flow = ControlFlow::Exit;
- }
- _ => {}
- },
- WindowEvent::Resized(physical_size) => {
- state.resize(*physical_size);
- }
- WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
- state.resize(**new_inner_size);
- }
- _ => {}
- }
- }
- Event::RedrawRequested(_) => {
- let now = std::time::Instant::now();
- let dt = now - last_render_time;
- last_render_time = now;
- state.update(dt);
- match state.render() {
- Ok(_) => {}
- // Recreate the swap_chain if lost
- Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
- // The system is out of memory, we should probably quit
- Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
- // All other errors (Outdated, Timeout) should be resolved by the next frame
- Err(e) => eprintln!("{:?}", e),
- }
- }
- _ => {}
- }
- });
- }
|