dfg.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. use rand::Rng;
  2. use std::iter;
  3. use cgmath::prelude::*;
  4. use wgpu::util::DeviceExt;
  5. use winit::{
  6. event::*,
  7. event_loop::{ControlFlow, EventLoop},
  8. window::Window,
  9. };
  10. use drk::gfx::{camera, model, texture};
  11. use model::{DrawModel, Vertex};
  12. use std::time::Instant;
  13. #[macro_use]
  14. extern crate lazy_static;
  15. lazy_static! {
  16. static ref START: Instant = Instant::now();
  17. }
  18. fn get_time() -> f32 {
  19. START.elapsed().as_secs_f32()
  20. }
  21. const FONT_BYTES: &[u8] = include_bytes!("../../res/font/PressStart2P-Regular.ttf");
  22. const NUM_INSTANCES_PER_ROW: u32 = 10;
  23. #[repr(C)]
  24. #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
  25. struct Uniforms {
  26. view_position: [f32; 4],
  27. view_proj: [[f32; 4]; 4],
  28. }
  29. impl Uniforms {
  30. fn new() -> Self {
  31. Self {
  32. view_position: [0.0; 4],
  33. view_proj: cgmath::Matrix4::identity().into(),
  34. }
  35. }
  36. fn update_view_proj(&mut self, camera: &camera::Camera, projection: &camera::Projection) {
  37. self.view_position = camera.position.to_homogeneous().into();
  38. self.view_proj = (projection.calc_matrix() * camera.calc_matrix()).into()
  39. }
  40. }
  41. struct Instance {
  42. position: cgmath::Vector3<f32>,
  43. rotation: cgmath::Quaternion<f32>,
  44. }
  45. impl Instance {
  46. fn to_raw(&self) -> InstanceRaw {
  47. InstanceRaw {
  48. model: (cgmath::Matrix4::from_translation(self.position)
  49. * cgmath::Matrix4::from(self.rotation))
  50. .into(),
  51. }
  52. }
  53. }
  54. #[repr(C)]
  55. #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
  56. struct InstanceRaw {
  57. #[allow(dead_code)]
  58. model: [[f32; 4]; 4],
  59. }
  60. impl model::Vertex for InstanceRaw {
  61. fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
  62. use std::mem;
  63. wgpu::VertexBufferLayout {
  64. array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress,
  65. // We need to switch from using a step mode of Vertex to Instance
  66. // This means that our shaders will only change to use the next
  67. // instance when the shader starts processing a new instance
  68. step_mode: wgpu::InputStepMode::Instance,
  69. attributes: &[
  70. wgpu::VertexAttribute {
  71. offset: 0,
  72. // While our vertex shader only uses locations 0, and 1 now, in later tutorials
  73. // we'll be using 2, 3, and 4, for Vertex. We'll start at
  74. // slot 5 not conflict with them later
  75. shader_location: 5,
  76. format: wgpu::VertexFormat::Float4,
  77. },
  78. // A mat4 takes up 4 vertex slots as it is technically 4 vec4s. We need to define a
  79. // slot for each vec4. We don't have to do this in code though.
  80. wgpu::VertexAttribute {
  81. offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress,
  82. shader_location: 6,
  83. format: wgpu::VertexFormat::Float4,
  84. },
  85. wgpu::VertexAttribute {
  86. offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress,
  87. shader_location: 7,
  88. format: wgpu::VertexFormat::Float4,
  89. },
  90. wgpu::VertexAttribute {
  91. offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress,
  92. shader_location: 8,
  93. format: wgpu::VertexFormat::Float4,
  94. },
  95. ],
  96. }
  97. }
  98. }
  99. #[repr(C)]
  100. #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
  101. struct Light {
  102. position: [f32; 3],
  103. // Due to uniforms requiring 16 byte (4 float) spacing, we need to use a padding field here
  104. _padding: u32,
  105. color: [f32; 3],
  106. }
  107. pub const UNBOUNDED_F32: f32 = std::f32::INFINITY;
  108. #[derive(Debug)]
  109. pub struct Text {
  110. pub position: cgmath::Vector2<f32>,
  111. pub bounds: cgmath::Vector2<f32>,
  112. pub color: cgmath::Vector4<f32>,
  113. pub text: String,
  114. pub size: f32,
  115. pub visible: bool,
  116. pub focused: bool,
  117. pub centered: bool,
  118. }
  119. impl Default for Text {
  120. fn default() -> Self {
  121. Self {
  122. position: (0.0, 0.0).into(),
  123. bounds: (UNBOUNDED_F32, UNBOUNDED_F32).into(),
  124. color: (1.0, 1.0, 1.0, 1.0).into(),
  125. text: String::new(),
  126. size: 16.0,
  127. visible: false,
  128. focused: false,
  129. centered: false,
  130. }
  131. }
  132. }
  133. const VERTEX_Z: f32 = 0.0;
  134. // (-1, 1) (1, 1)
  135. // +-----------------------+
  136. // | |
  137. // | |
  138. // | |
  139. // | |
  140. // | |
  141. // | |
  142. // | |
  143. // +-----------------------+
  144. // (-1, -1) (1, -1)
  145. const VERTICES: &[model::ModelVertex] = &[
  146. // top left
  147. model::ModelVertex {
  148. position: [-1.0, 1.0, VERTEX_Z],
  149. tex_coords: [0.0, 0.0],
  150. normal: [0.0, 0.0, -1.0],
  151. },
  152. // bottom left
  153. model::ModelVertex {
  154. position: [-1.0, 0.5, VERTEX_Z],
  155. tex_coords: [0.0, 1.0],
  156. normal: [0.0, 0.0, -1.0],
  157. },
  158. // bottom right
  159. model::ModelVertex {
  160. position: [-0.5, 0.5, VERTEX_Z],
  161. tex_coords: [1.0, 1.0],
  162. normal: [0.0, 0.0, -1.0],
  163. },
  164. // top right
  165. model::ModelVertex {
  166. position: [-0.5, 1.0, VERTEX_Z],
  167. tex_coords: [1.0, 0.0],
  168. normal: [0.0, 0.0, -1.0],
  169. },
  170. ];
  171. //const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4];
  172. const INDICES: &[u16] = &[0, 1, 2, 0, 2, 3];
  173. #[allow(dead_code)]
  174. struct State {
  175. surface: wgpu::Surface,
  176. device: wgpu::Device,
  177. queue: wgpu::Queue,
  178. sc_desc: wgpu::SwapChainDescriptor,
  179. swap_chain: wgpu::SwapChain,
  180. render_pipeline: wgpu::RenderPipeline,
  181. obj_model: model::Model,
  182. camera: camera::Camera, // UPDATED!
  183. projection: camera::Projection, // NEW!
  184. camera_controller: camera::CameraController, // UPDATED!
  185. uniforms: Uniforms,
  186. uniform_buffer: wgpu::Buffer,
  187. uniform_bind_group: wgpu::BindGroup,
  188. instances: Vec<Instance>,
  189. #[allow(dead_code)]
  190. instance_buffer: wgpu::Buffer,
  191. depth_texture: texture::Texture,
  192. size: winit::dpi::PhysicalSize<u32>,
  193. light: Light,
  194. light_buffer: wgpu::Buffer,
  195. light_bind_group: wgpu::BindGroup,
  196. light_render_pipeline: wgpu::RenderPipeline,
  197. ui_render_pipeline: wgpu::RenderPipeline,
  198. vertex_buffer: wgpu::Buffer,
  199. index_buffer: wgpu::Buffer,
  200. num_indices: u32,
  201. #[allow(dead_code)]
  202. diffuse_texture: texture::Texture,
  203. diffuse_bind_group: wgpu::BindGroup,
  204. #[allow(dead_code)]
  205. cartoon_texture: texture::Texture,
  206. cartoon_bind_group: wgpu::BindGroup,
  207. glyph_brush: wgpu_glyph::GlyphBrush<()>,
  208. staging_belt: wgpu::util::StagingBelt,
  209. is_space_pressed: bool,
  210. mouse_pressed: bool,
  211. }
  212. fn create_render_pipeline(
  213. device: &wgpu::Device,
  214. layout: &wgpu::PipelineLayout,
  215. color_format: wgpu::TextureFormat,
  216. depth_format: Option<wgpu::TextureFormat>,
  217. vertex_layouts: &[wgpu::VertexBufferLayout],
  218. vs_src: wgpu::ShaderModuleDescriptor,
  219. fs_src: wgpu::ShaderModuleDescriptor,
  220. ) -> wgpu::RenderPipeline {
  221. let vs_module = device.create_shader_module(&vs_src);
  222. let fs_module = device.create_shader_module(&fs_src);
  223. device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
  224. label: Some("Render Pipeline"),
  225. layout: Some(&layout),
  226. vertex: wgpu::VertexState {
  227. module: &vs_module,
  228. entry_point: "main",
  229. buffers: vertex_layouts,
  230. },
  231. fragment: Some(wgpu::FragmentState {
  232. module: &fs_module,
  233. entry_point: "main",
  234. targets: &[wgpu::ColorTargetState {
  235. format: color_format,
  236. alpha_blend: wgpu::BlendState::REPLACE,
  237. color_blend: wgpu::BlendState::REPLACE,
  238. write_mask: wgpu::ColorWrite::ALL,
  239. }],
  240. }),
  241. primitive: wgpu::PrimitiveState {
  242. topology: wgpu::PrimitiveTopology::TriangleList,
  243. strip_index_format: None,
  244. front_face: wgpu::FrontFace::Ccw,
  245. cull_mode: wgpu::CullMode::Back,
  246. // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
  247. polygon_mode: wgpu::PolygonMode::Fill,
  248. },
  249. depth_stencil: depth_format.map(|format| wgpu::DepthStencilState {
  250. format,
  251. depth_write_enabled: true,
  252. depth_compare: wgpu::CompareFunction::Less,
  253. stencil: wgpu::StencilState::default(),
  254. bias: wgpu::DepthBiasState::default(),
  255. // Setting this to true requires Features::DEPTH_CLAMPING
  256. clamp_depth: false,
  257. }),
  258. multisample: wgpu::MultisampleState {
  259. count: 1,
  260. mask: !0,
  261. alpha_to_coverage_enabled: false,
  262. },
  263. })
  264. }
  265. impl State {
  266. async fn new(window: &Window) -> Self {
  267. let size = window.inner_size();
  268. // The instance is a handle to our GPU
  269. // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
  270. let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
  271. let surface = unsafe { instance.create_surface(window) };
  272. let adapter = instance
  273. .request_adapter(&wgpu::RequestAdapterOptions {
  274. power_preference: wgpu::PowerPreference::default(),
  275. compatible_surface: Some(&surface),
  276. })
  277. .await
  278. .unwrap();
  279. let (device, queue) = adapter
  280. .request_device(
  281. &wgpu::DeviceDescriptor {
  282. label: None,
  283. features: wgpu::Features::empty(),
  284. limits: wgpu::Limits::default(),
  285. },
  286. None, // Trace path
  287. )
  288. .await
  289. .unwrap();
  290. let sc_desc = wgpu::SwapChainDescriptor {
  291. usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
  292. format: adapter.get_swap_chain_preferred_format(&surface),
  293. width: size.width,
  294. height: size.height,
  295. present_mode: wgpu::PresentMode::Fifo,
  296. };
  297. let swap_chain = device.create_swap_chain(&surface, &sc_desc);
  298. let texture_bind_group_layout =
  299. device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
  300. entries: &[
  301. wgpu::BindGroupLayoutEntry {
  302. binding: 0,
  303. visibility: wgpu::ShaderStage::FRAGMENT,
  304. ty: wgpu::BindingType::Texture {
  305. multisampled: false,
  306. view_dimension: wgpu::TextureViewDimension::D2,
  307. sample_type: wgpu::TextureSampleType::Float { filterable: false },
  308. },
  309. count: None,
  310. },
  311. wgpu::BindGroupLayoutEntry {
  312. binding: 1,
  313. visibility: wgpu::ShaderStage::FRAGMENT,
  314. ty: wgpu::BindingType::Sampler {
  315. comparison: false,
  316. filtering: true,
  317. },
  318. count: None,
  319. },
  320. ],
  321. label: Some("texture_bind_group_layout"),
  322. });
  323. let camera = camera::Camera::new((0.0, 5.0, 10.0), cgmath::Deg(-90.0), cgmath::Deg(-20.0));
  324. let projection =
  325. camera::Projection::new(sc_desc.width, sc_desc.height, cgmath::Deg(45.0), 0.1, 100.0);
  326. let camera_controller = camera::CameraController::new(4.0, 0.4);
  327. let mut uniforms = Uniforms::new();
  328. uniforms.update_view_proj(&camera, &projection);
  329. let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  330. label: Some("Uniform Buffer"),
  331. contents: bytemuck::cast_slice(&[uniforms]),
  332. usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
  333. });
  334. const SPACE_BETWEEN: f32 = 3.0;
  335. let instances = (0..NUM_INSTANCES_PER_ROW)
  336. .flat_map(|z| {
  337. (0..NUM_INSTANCES_PER_ROW).map(move |x| {
  338. let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
  339. let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
  340. let y = 0.0;
  341. let position = cgmath::Vector3 { x, y, z };
  342. let rotation = cgmath::Quaternion::from_axis_angle(
  343. cgmath::Vector3::unit_z(),
  344. cgmath::Deg(180.0 + 0.0),
  345. );
  346. Instance { position, rotation }
  347. })
  348. })
  349. .collect::<Vec<_>>();
  350. let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
  351. let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  352. label: Some("Instance Buffer"),
  353. contents: bytemuck::cast_slice(&instance_data),
  354. usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
  355. });
  356. let uniform_bind_group_layout =
  357. device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
  358. entries: &[wgpu::BindGroupLayoutEntry {
  359. binding: 0,
  360. visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
  361. ty: wgpu::BindingType::Buffer {
  362. ty: wgpu::BufferBindingType::Uniform,
  363. has_dynamic_offset: false,
  364. min_binding_size: None,
  365. },
  366. count: None,
  367. }],
  368. label: Some("uniform_bind_group_layout"),
  369. });
  370. let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  371. layout: &uniform_bind_group_layout,
  372. entries: &[wgpu::BindGroupEntry {
  373. binding: 0,
  374. resource: uniform_buffer.as_entire_binding(),
  375. }],
  376. label: Some("uniform_bind_group"),
  377. });
  378. let res_dir = std::path::Path::new("res/model/");
  379. let obj_model = model::Model::load(
  380. &device,
  381. &queue,
  382. &texture_bind_group_layout,
  383. res_dir.join("earth.obj"),
  384. )
  385. .unwrap();
  386. let light = Light {
  387. position: [4.0, 4.0, 2.0],
  388. _padding: 0,
  389. color: [1.0, 1.0, 1.0],
  390. };
  391. let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  392. label: Some("Light VB"),
  393. contents: bytemuck::cast_slice(&[light]),
  394. usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
  395. });
  396. let light_bind_group_layout =
  397. device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
  398. entries: &[wgpu::BindGroupLayoutEntry {
  399. binding: 0,
  400. visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
  401. ty: wgpu::BindingType::Buffer {
  402. ty: wgpu::BufferBindingType::Uniform,
  403. has_dynamic_offset: false,
  404. min_binding_size: None,
  405. },
  406. count: None,
  407. }],
  408. label: None,
  409. });
  410. let light_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  411. layout: &light_bind_group_layout,
  412. entries: &[wgpu::BindGroupEntry {
  413. binding: 0,
  414. resource: light_buffer.as_entire_binding(),
  415. }],
  416. label: None,
  417. });
  418. let depth_texture =
  419. texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
  420. let render_pipeline_layout =
  421. device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
  422. label: Some("Render Pipeline Layout"),
  423. bind_group_layouts: &[
  424. &texture_bind_group_layout,
  425. &uniform_bind_group_layout,
  426. &light_bind_group_layout,
  427. ],
  428. push_constant_ranges: &[],
  429. });
  430. let render_pipeline = create_render_pipeline(
  431. &device,
  432. &render_pipeline_layout,
  433. sc_desc.format,
  434. Some(texture::Texture::DEPTH_FORMAT),
  435. &[model::ModelVertex::desc(), InstanceRaw::desc()],
  436. wgpu::include_spirv!("../../res/shader/shader.vert.spv"),
  437. wgpu::include_spirv!("../../res/shader/shader.frag.spv"),
  438. );
  439. let light_render_pipeline = {
  440. let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
  441. label: Some("Light Pipeline Layout"),
  442. bind_group_layouts: &[&uniform_bind_group_layout, &light_bind_group_layout],
  443. push_constant_ranges: &[],
  444. });
  445. create_render_pipeline(
  446. &device,
  447. &layout,
  448. sc_desc.format,
  449. Some(texture::Texture::DEPTH_FORMAT),
  450. &[model::ModelVertex::desc()],
  451. wgpu::include_spirv!("../../res/shader/light.vert.spv"),
  452. wgpu::include_spirv!("../../res/shader/light.frag.spv"),
  453. )
  454. };
  455. //-------------------
  456. let texture_bind_group_layout =
  457. device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
  458. entries: &[
  459. wgpu::BindGroupLayoutEntry {
  460. binding: 0,
  461. visibility: wgpu::ShaderStage::FRAGMENT,
  462. ty: wgpu::BindingType::Texture {
  463. multisampled: false,
  464. view_dimension: wgpu::TextureViewDimension::D2,
  465. sample_type: wgpu::TextureSampleType::Float { filterable: false },
  466. },
  467. count: None,
  468. },
  469. wgpu::BindGroupLayoutEntry {
  470. binding: 1,
  471. visibility: wgpu::ShaderStage::FRAGMENT,
  472. ty: wgpu::BindingType::Sampler {
  473. comparison: false,
  474. filtering: true,
  475. },
  476. count: None,
  477. },
  478. ],
  479. label: Some("texture_bind_group_layout"),
  480. });
  481. let diffuse_bytes = include_bytes!("../../res/img/absolutely-proprietary.png");
  482. let diffuse_texture =
  483. texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "stallman1").unwrap();
  484. let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  485. layout: &texture_bind_group_layout,
  486. entries: &[
  487. wgpu::BindGroupEntry {
  488. binding: 0,
  489. resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
  490. },
  491. wgpu::BindGroupEntry {
  492. binding: 1,
  493. resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
  494. },
  495. ],
  496. label: Some("diffuse_bind_group"),
  497. });
  498. let cartoon_bytes = include_bytes!("../../res/img/absolutely-proprietary2.png");
  499. let cartoon_texture =
  500. texture::Texture::from_bytes(&device, &queue, cartoon_bytes, "stallman2").unwrap();
  501. let cartoon_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  502. layout: &texture_bind_group_layout,
  503. entries: &[
  504. wgpu::BindGroupEntry {
  505. binding: 0,
  506. resource: wgpu::BindingResource::TextureView(&cartoon_texture.view),
  507. },
  508. wgpu::BindGroupEntry {
  509. binding: 1,
  510. resource: wgpu::BindingResource::Sampler(&cartoon_texture.sampler),
  511. },
  512. ],
  513. label: Some("cartoon_bind_group"),
  514. });
  515. let render_pipeline_layout =
  516. device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
  517. label: Some("Render Pipeline Layout"),
  518. bind_group_layouts: &[&texture_bind_group_layout],
  519. push_constant_ranges: &[],
  520. });
  521. let ui_render_pipeline = create_render_pipeline(
  522. &device,
  523. &render_pipeline_layout,
  524. sc_desc.format,
  525. Some(texture::Texture::DEPTH_FORMAT),
  526. &[model::ModelVertex::desc()],
  527. wgpu::include_spirv!("../../res/shader/ui_shader.vert.spv"),
  528. wgpu::include_spirv!("../../res/shader/ui_shader.frag.spv"),
  529. );
  530. let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  531. label: Some("Vertex Buffer"),
  532. contents: bytemuck::cast_slice(VERTICES),
  533. usage: wgpu::BufferUsage::VERTEX,
  534. });
  535. let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  536. label: Some("Index Buffer"),
  537. contents: bytemuck::cast_slice(INDICES),
  538. usage: wgpu::BufferUsage::INDEX,
  539. });
  540. let num_indices = INDICES.len() as u32;
  541. let font = wgpu_glyph::ab_glyph::FontArc::try_from_slice(FONT_BYTES).unwrap();
  542. let glyph_brush =
  543. wgpu_glyph::GlyphBrushBuilder::using_font(font).build(&device, sc_desc.format);
  544. let staging_belt = wgpu::util::StagingBelt::new(1024);
  545. Self {
  546. surface,
  547. device,
  548. queue,
  549. sc_desc,
  550. swap_chain,
  551. render_pipeline,
  552. obj_model,
  553. camera,
  554. projection,
  555. camera_controller,
  556. uniform_buffer,
  557. uniform_bind_group,
  558. uniforms,
  559. instances,
  560. instance_buffer,
  561. depth_texture,
  562. size,
  563. light,
  564. light_buffer,
  565. light_bind_group,
  566. light_render_pipeline,
  567. ui_render_pipeline,
  568. vertex_buffer,
  569. index_buffer,
  570. num_indices,
  571. diffuse_texture,
  572. diffuse_bind_group,
  573. cartoon_texture,
  574. cartoon_bind_group,
  575. glyph_brush,
  576. staging_belt,
  577. is_space_pressed: true,
  578. mouse_pressed: false,
  579. }
  580. }
  581. fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
  582. self.projection.resize(new_size.width, new_size.height);
  583. self.size = new_size;
  584. self.sc_desc.width = new_size.width;
  585. self.sc_desc.height = new_size.height;
  586. self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
  587. self.depth_texture =
  588. texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
  589. }
  590. fn input(&mut self, event: &DeviceEvent) -> bool {
  591. match event {
  592. DeviceEvent::Key(KeyboardInput {
  593. virtual_keycode: Some(key),
  594. state,
  595. ..
  596. }) => self.camera_controller.process_keyboard(*key, *state),
  597. DeviceEvent::MouseWheel { delta, .. } => {
  598. self.camera_controller.process_scroll(delta);
  599. true
  600. }
  601. DeviceEvent::Button {
  602. button: 1, // Left Mouse Button
  603. state,
  604. } => {
  605. self.mouse_pressed = *state == ElementState::Pressed;
  606. true
  607. }
  608. DeviceEvent::MouseMotion { delta } => {
  609. if self.mouse_pressed {
  610. self.camera_controller.process_mouse(delta.0, delta.1);
  611. }
  612. true
  613. }
  614. _ => false,
  615. }
  616. }
  617. fn update(&mut self, dt: std::time::Duration) {
  618. if rand::thread_rng().gen_range(0, 5) == 0 {
  619. self.is_space_pressed = !self.is_space_pressed;
  620. }
  621. self.camera_controller.update_camera(&mut self.camera, dt);
  622. self.uniforms
  623. .update_view_proj(&self.camera, &self.projection);
  624. self.queue.write_buffer(
  625. &self.uniform_buffer,
  626. 0,
  627. bytemuck::cast_slice(&[self.uniforms]),
  628. );
  629. let time = get_time();
  630. const SPACE_BETWEEN: f32 = 3.0;
  631. let instances = (0..NUM_INSTANCES_PER_ROW)
  632. .flat_map(|z| {
  633. (0..NUM_INSTANCES_PER_ROW).map(move |x| {
  634. let x = SPACE_BETWEEN * (x as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
  635. let z = SPACE_BETWEEN * (z as f32 - NUM_INSTANCES_PER_ROW as f32 / 2.0);
  636. //println!("{} {} {}", x, z, time);
  637. let y = ((x / 3.0 + time).sin() + (z / 3.0 + time).cos()) * 1.5;
  638. let position = cgmath::Vector3 { x, y, z };
  639. let rotation = cgmath::Quaternion::from_axis_angle(
  640. cgmath::Vector3::unit_z(),
  641. cgmath::Deg(180.0 + 0.0),
  642. );
  643. Instance { position, rotation }
  644. })
  645. })
  646. .collect::<Vec<_>>();
  647. let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
  648. self.queue.write_buffer(
  649. &self.instance_buffer,
  650. 0,
  651. bytemuck::cast_slice(&instance_data),
  652. );
  653. // Update the light
  654. let old_position: cgmath::Vector3<_> = self.light.position.into();
  655. self.light.position =
  656. (cgmath::Quaternion::from_axis_angle((0.0, 1.0, 0.0).into(), cgmath::Deg(1.0))
  657. * old_position)
  658. .into();
  659. self.queue
  660. .write_buffer(&self.light_buffer, 0, bytemuck::cast_slice(&[self.light]));
  661. }
  662. fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
  663. let frame = self.swap_chain.get_current_frame()?.output;
  664. let mut encoder = self
  665. .device
  666. .create_command_encoder(&wgpu::CommandEncoderDescriptor {
  667. label: Some("Render Encoder"),
  668. });
  669. {
  670. let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
  671. label: Some("Render Pass"),
  672. color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
  673. attachment: &frame.view,
  674. resolve_target: None,
  675. ops: wgpu::Operations {
  676. load: wgpu::LoadOp::Clear(wgpu::Color {
  677. r: 0.1,
  678. g: 0.2,
  679. b: 0.3,
  680. a: 1.0,
  681. }),
  682. store: true,
  683. },
  684. }],
  685. depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
  686. attachment: &self.depth_texture.view,
  687. depth_ops: Some(wgpu::Operations {
  688. load: wgpu::LoadOp::Clear(1.0),
  689. store: true,
  690. }),
  691. stencil_ops: None,
  692. }),
  693. });
  694. render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
  695. //render_pass.set_pipeline(&self.light_render_pipeline);
  696. //render_pass.draw_light_model(
  697. // &self.obj_model,
  698. // &self.uniform_bind_group,
  699. // &self.light_bind_group,
  700. //);
  701. render_pass.set_pipeline(&self.render_pipeline);
  702. render_pass.draw_model_instanced(
  703. &self.obj_model,
  704. 0..self.instances.len() as u32,
  705. &self.uniform_bind_group,
  706. &self.light_bind_group,
  707. );
  708. let bind_group = if self.is_space_pressed {
  709. &self.cartoon_bind_group
  710. } else {
  711. &self.diffuse_bind_group
  712. };
  713. render_pass.set_pipeline(&self.ui_render_pipeline);
  714. render_pass.set_bind_group(0, bind_group, &[]);
  715. render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
  716. render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
  717. render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
  718. }
  719. let play_text = Text {
  720. position: (40.0, 40.0).into(),
  721. color: (1.0, 1.0, 1.0, 1.0).into(),
  722. text: String::from("Absolutely Proprietary"),
  723. size: 32.0,
  724. centered: false,
  725. ..Default::default()
  726. };
  727. draw_text(&play_text, &mut self.glyph_brush);
  728. self.glyph_brush
  729. .draw_queued(
  730. &self.device,
  731. &mut self.staging_belt,
  732. &mut encoder,
  733. &frame.view,
  734. self.sc_desc.width,
  735. self.sc_desc.height,
  736. )
  737. .unwrap();
  738. self.staging_belt.finish();
  739. self.queue.submit(iter::once(encoder.finish()));
  740. Ok(())
  741. }
  742. }
  743. fn draw_text(text: &Text, glyph_brush: &mut wgpu_glyph::GlyphBrush<()>) {
  744. let layout = wgpu_glyph::Layout::default().h_align(if text.centered {
  745. wgpu_glyph::HorizontalAlign::Center
  746. } else {
  747. wgpu_glyph::HorizontalAlign::Left
  748. });
  749. let section = wgpu_glyph::Section {
  750. screen_position: text.position.into(),
  751. bounds: text.bounds.into(),
  752. layout,
  753. ..Default::default()
  754. }
  755. .add_text(
  756. wgpu_glyph::Text::new(&text.text)
  757. .with_color(text.color)
  758. .with_scale(if text.focused {
  759. text.size + 8.0
  760. } else {
  761. text.size
  762. }),
  763. );
  764. glyph_brush.queue(section);
  765. }
  766. fn main() {
  767. env_logger::init();
  768. let event_loop = EventLoop::new();
  769. let title = env!("CARGO_PKG_NAME");
  770. let window = winit::window::WindowBuilder::new()
  771. .with_title(title)
  772. .build(&event_loop)
  773. .unwrap();
  774. use futures::executor::block_on;
  775. let mut state = block_on(State::new(&window));
  776. let mut last_render_time = std::time::Instant::now();
  777. event_loop.run(move |event, _, control_flow| {
  778. *control_flow = ControlFlow::Poll;
  779. match event {
  780. Event::MainEventsCleared => window.request_redraw(),
  781. Event::DeviceEvent {
  782. ref event,
  783. .. // We're not using device_id currently
  784. } => {
  785. state.input(event);
  786. }
  787. Event::WindowEvent {
  788. ref event,
  789. window_id,
  790. } if window_id == window.id() => {
  791. match event {
  792. WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
  793. WindowEvent::KeyboardInput { input, .. } => match input {
  794. KeyboardInput {
  795. state: ElementState::Pressed,
  796. virtual_keycode: Some(VirtualKeyCode::Escape),
  797. ..
  798. } => {
  799. *control_flow = ControlFlow::Exit;
  800. }
  801. _ => {}
  802. },
  803. WindowEvent::Resized(physical_size) => {
  804. state.resize(*physical_size);
  805. }
  806. WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
  807. state.resize(**new_inner_size);
  808. }
  809. _ => {}
  810. }
  811. }
  812. Event::RedrawRequested(_) => {
  813. let now = std::time::Instant::now();
  814. let dt = now - last_render_time;
  815. last_render_time = now;
  816. state.update(dt);
  817. match state.render() {
  818. Ok(_) => {}
  819. // Recreate the swap_chain if lost
  820. Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
  821. // The system is out of memory, we should probably quit
  822. Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
  823. // All other errors (Outdated, Timeout) should be resolved by the next frame
  824. Err(e) => eprintln!("{:?}", e),
  825. }
  826. }
  827. _ => {}
  828. }
  829. });
  830. }