#![allow(non_snake_case)] #![allow(unused_variables)] use anyhow::Result; use cgmath::prelude::*; use std::path::PathBuf; use std::time::Duration; use wgpu::util::DeviceExt; use winit::event::*; use Graphics::Camera::*; use Graphics::Render::*; use Graphics::{Display, Runtime, State}; struct Cubes { render_pipeline: wgpu::RenderPipeline, obj_model: Model, camera: Camera, camera_controller: CameraController, camera_uniform: CameraUniform, camera_buffer: wgpu::Buffer, camera_bind_group: wgpu::BindGroup, instances: Vec, instance_buffer: wgpu::Buffer, depth_texture: Texture, } impl State for Cubes { fn Init(display: &Display) -> Result { let texture_bind_group_layout = display .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, ty: wgpu::BindingType::Sampler { comparison: false, filtering: true, }, count: None, }, ], label: Some("texture_bind_group_layout"), }); // Camera let camera = Camera { eye: (0.0, 5.0, -10.0).into(), target: (0.0, 0.0, 0.0).into(), up: cgmath::Vector3::unit_y(), aspect: display.config.width as f32 / display.config.height as f32, fovy: 45.0, znear: 0.1, zfar: 100.0, }; let camera_controller = CameraController::New(0.2); let mut camera_uniform = CameraUniform::New(); camera_uniform.UpdateViewProjection(&camera); let camera_buffer = display .device .create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Camera Buffer"), contents: bytemuck::cast_slice(&[camera_uniform]), usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::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 position = cgmath::Vector3 { x, y: 0.0, z }; let rotation = if position.is_zero() { cgmath::Quaternion::from_axis_angle( cgmath::Vector3::unit_z(), cgmath::Deg(0.0), ) } else { cgmath::Quaternion::from_axis_angle(position.normalize(), cgmath::Deg(45.0)) }; Instance { position, rotation } }) }) .collect::>(); let instance_data = instances.iter().map(Instance::ToRaw).collect::>(); let instance_buffer = display .device .create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Instance Buffer"), contents: bytemuck::cast_slice(&instance_data), usage: wgpu::BufferUsages::VERTEX, }); let camera_bind_group_layout = display .device .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::VERTEX, ty: wgpu::BindingType::Buffer { ty: wgpu::BufferBindingType::Uniform, has_dynamic_offset: false, min_binding_size: None, }, count: None, }], label: Some("camera_bind_group_layout"), }); let camera_bind_group = display .device .create_bind_group(&wgpu::BindGroupDescriptor { layout: &camera_bind_group_layout, entries: &[wgpu::BindGroupEntry { binding: 0, resource: camera_buffer.as_entire_binding(), }], label: Some("camera_bind_group"), }); // Model let obj_model = Model::Load( &display.device, &display.queue, &texture_bind_group_layout, PathBuf::from("./Content/SM_Cube.obj"), ) .unwrap(); // Shader let shader = display .device .create_shader_module(&wgpu::ShaderModuleDescriptor { label: Some("shader.wgsl"), source: wgpu::ShaderSource::Wgsl(include_str!("../Shaders/Cubes.wgsl").into()), }); // Texture let depth_texture = Texture::CreateDepthTexture(&display.device, &display.config, "depth_texture"); // Pipeline let render_pipeline_layout = display .device .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Render Pipeline Layout"), bind_group_layouts: &[&texture_bind_group_layout, &camera_bind_group_layout], push_constant_ranges: &[], }); let render_pipeline = display .device .create_render_pipeline(&wgpu::RenderPipelineDescriptor { label: Some("Render Pipeline"), layout: Some(&render_pipeline_layout), vertex: wgpu::VertexState { module: &shader, entry_point: "vs_main", buffers: &[ModelVertex::GetDescriptor(), InstanceRaw::GetDescriptor()], }, fragment: Some(wgpu::FragmentState { module: &shader, entry_point: "fs_main", targets: &[wgpu::ColorTargetState { format: display.config.format, blend: Some(wgpu::BlendState { color: wgpu::BlendComponent::REPLACE, alpha: wgpu::BlendComponent::REPLACE, }), write_mask: wgpu::ColorWrites::ALL, }], }), primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE polygon_mode: wgpu::PolygonMode::Fill, // Requires Features::DEPTH_CLAMPING clamp_depth: false, // Requires Features::CONSERVATIVE_RASTERIZATION conservative: false, }, depth_stencil: Some(wgpu::DepthStencilState { format: Texture::DEPTH_FORMAT, depth_write_enabled: true, depth_compare: wgpu::CompareFunction::Less, stencil: wgpu::StencilState::default(), bias: wgpu::DepthBiasState::default(), }), multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false, }, }); Ok(Self { render_pipeline, obj_model, camera, camera_controller, camera_buffer, camera_bind_group, camera_uniform, instances, instance_buffer, depth_texture, }) } fn Input(&mut self, display: &Display, event: &WindowEvent) -> bool { self.camera_controller.ProcessEvents(event) } fn Update(&mut self, display: &Display, delta: Duration) { self.camera_controller.UpdateCamera(&mut self.camera); self.camera_uniform.UpdateViewProjection(&self.camera); display.queue.write_buffer( &self.camera_buffer, 0, bytemuck::cast_slice(&[self.camera_uniform]), ); } fn Resize(&mut self, display: &Display) { self.depth_texture = Texture::CreateDepthTexture(&display.device, &display.config, "depth_texture"); } fn Draw(&mut self, display: &mut Display) -> Result<(), wgpu::SurfaceError> { let output = display.surface.get_current_texture().unwrap(); let view = output .texture .create_view(&wgpu::TextureViewDescriptor::default()); let mut encoder = display .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::RenderPassColorAttachment { view: &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::RenderPassDepthStencilAttachment { view: &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.render_pipeline); render_pass.DrawModelInstanced( &self.obj_model, 0..self.instances.len() as u32, &self.camera_bind_group, ); } display.queue.submit(std::iter::once(encoder.finish())); output.present(); Ok(()) } } fn main() -> Result<()> { Runtime::Execute::() }