removed camera research

pull/131/head
Ben Hansen 3 years ago
parent 99fd6523d7
commit 733683cf6f

3347
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -88,7 +88,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -1,27 +0,0 @@
[package]
name = "camera"
version = "0.1.0"
authors = ["Ben Hansen <bhbenjaminhansen@gmail.com>"]
edition = "2018"
[dependencies]
bytemuck = { version = "1.4", features = [ "derive" ] }
env_logger = "0.7"
failure = "0.1"
futures = "0.3.5"
image = "0.23"
log = "0.4"
# tobj = "1"
wgpu = "0.5.0"
winit = "0.22"
imgui-wgpu = "0.7"
[dependencies.cgmath]
version = "0.17"
features = ["swizzle"]
[build-dependencies]
shaderc = "0.6"
glob = "0.3"
failure = "0.1"
fs_extra = "1.1"

@ -1,94 +0,0 @@
use failure::bail;
use fs_extra::copy_items;
use fs_extra::dir::CopyOptions;
use glob::glob;
use std::env;
use std::fs::{read_to_string, write};
use std::path::PathBuf;
fn main() {
copy_res();
compile_shaders();
}
fn copy_res() {
// This tells cargo to rerun this script if something in /res/ changes.
println!("cargo:rerun-if-changed=res/*");
let out_dir = env::var("OUT_DIR").unwrap();
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
copy_items(&paths_to_copy, out_dir, &copy_options).unwrap();
}
fn compile_shaders() {
// This tells cargo to rerun this script if something in /src/ changes.
println!("cargo:rerun-if-changed=src/*");
// Collect all shaders recursively within /src/
let mut shader_paths = [
glob("./src/**/*.vert").unwrap(),
glob("./src/**/*.frag").unwrap(),
glob("./src/**/*.comp").unwrap(),
];
// This could be parallelized
let shaders = shader_paths
.iter_mut()
.flatten()
.map(|glob_result| ShaderData::load(glob_result.unwrap()).unwrap())
.collect::<Vec<ShaderData>>();
let mut compiler = shaderc::Compiler::new().unwrap();
// This can't be parallelized. The [shaderc::Compiler] is not
// thread safe. Also, it creates a lot of resources. You could
// spawn multiple processes to handle this, but it would probably
// be better just to only compile shaders that have been changed
// recently.
for shader in shaders {
let compiled = compiler
.compile_into_spirv(
&shader.src,
shader.kind,
&shader.src_path.to_str().unwrap(),
"main",
None,
)
.unwrap();
write(shader.spv_path, compiled.as_binary_u8()).unwrap();
}
// panic!("Debugging...");
}
struct ShaderData {
src: String,
src_path: PathBuf,
spv_path: PathBuf,
kind: shaderc::ShaderKind,
}
impl ShaderData {
pub fn load(src_path: PathBuf) -> Result<Self, failure::Error> {
let extension = src_path.extension().unwrap().to_str().unwrap();
let kind = match extension {
"vert" => shaderc::ShaderKind::Vertex,
"frag" => shaderc::ShaderKind::Fragment,
"comp" => shaderc::ShaderKind::Compute,
_ => bail!("Unsupported shader: {}", src_path.display()),
};
let src = read_to_string(src_path.clone())?;
let spv_path = src_path.with_extension(format!("{}.spv", extension));
Ok(Self {
src,
src_path,
spv_path,
kind,
})
}
}

@ -1,160 +0,0 @@
use cgmath::prelude::*;
use cgmath::*;
use std::f32::consts::FRAC_PI_2;
use std::time::Duration;
use winit::event::*;
#[rustfmt::skip]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.0, 0.0, 0.5, 1.0,
);
#[derive(Debug)]
pub struct Camera {
position: Point3<f32>,
yaw: Rad<f32>,
pitch: Rad<f32>,
}
impl Camera {
pub fn new<V: Into<Point3<f32>>, Y: Into<Rad<f32>>, P: Into<Rad<f32>>>(
position: V,
yaw: Y,
pitch: P,
) -> Self {
Self {
position: position.into(),
yaw: yaw.into(),
pitch: pitch.into(),
}
}
pub fn calc_matrix(&self) -> Matrix4<f32> {
Matrix4::look_at_dir(
self.position,
Vector3::new(self.yaw.0.cos(), self.pitch.0.sin(), self.yaw.0.sin()).normalize(),
Vector3::unit_y(),
)
}
}
pub struct Projection {
aspect: f32,
fovy: Rad<f32>,
znear: f32,
zfar: f32,
}
impl Projection {
pub fn new<F: Into<Rad<f32>>>(width: u32, height: u32, fovy: F, znear: f32, zfar: f32) -> Self {
Self {
aspect: width as f32 / height as f32,
fovy: fovy.into(),
znear,
zfar,
}
}
pub fn resize(&mut self, width: u32, height: u32) {
self.aspect = width as f32 / height as f32;
}
pub fn calc_matrix(&self) -> Matrix4<f32> {
OPENGL_TO_WGPU_MATRIX * perspective(self.fovy, self.aspect, self.znear, self.zfar)
}
}
#[derive(Debug)]
pub struct CameraController {
amount_left: f32,
amount_right: f32,
amount_forward: f32,
amount_backward: f32,
rotate_horizontal: f32,
rotate_vertical: f32,
speed: f32,
is_dirty: bool,
}
impl CameraController {
pub fn new(speed: f32) -> Self {
Self {
amount_left: 0.0,
amount_right: 0.0,
amount_forward: 0.0,
amount_backward: 0.0,
rotate_horizontal: 0.0,
rotate_vertical: 0.0,
speed,
is_dirty: false,
}
}
pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool {
let amount = if state == ElementState::Pressed {
1.0
} else {
0.0
};
match key {
VirtualKeyCode::W | VirtualKeyCode::Up => {
self.amount_forward = amount;
self.is_dirty = true;
true
}
VirtualKeyCode::S | VirtualKeyCode::Down => {
self.amount_backward = amount;
self.is_dirty = true;
true
}
VirtualKeyCode::A | VirtualKeyCode::Left => {
self.amount_left = amount;
self.is_dirty = true;
true
}
VirtualKeyCode::D | VirtualKeyCode::Right => {
self.amount_right = amount;
self.is_dirty = true;
true
}
_ => false,
}
}
pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) {
self.rotate_horizontal = mouse_dx as f32;
self.rotate_vertical = mouse_dy as f32;
self.is_dirty = true;
}
pub fn update_camera(&mut self, camera: &mut Camera, dt: Duration) {
self.is_dirty = false;
let dt = dt.as_secs_f32();
let (sin, cos) = camera.yaw.0.sin_cos();
let forward = Vector3::new(cos, 0.0, sin).normalize();
let right = Vector3::new(sin, 0.0, cos).normalize();
camera.position += forward * (self.amount_forward - self.amount_backward) * self.speed * dt;
camera.position += right * (self.amount_right - self.amount_left) * self.speed * dt;
camera.yaw += Rad(-self.rotate_horizontal) * dt;
camera.pitch += Rad(self.rotate_vertical) * dt;
self.rotate_horizontal = 0.0;
self.rotate_vertical = 0.0;
if camera.pitch < -Rad(FRAC_PI_2) {
camera.pitch = -Rad(FRAC_PI_2);
} else if camera.pitch > Rad(FRAC_PI_2) {
camera.pitch = Rad(FRAC_PI_2);
}
}
pub fn is_dirty(&self) -> bool {
self.is_dirty
}
}

@ -1,59 +0,0 @@
use cgmath::*;
use std::mem::size_of;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Vertex {
position: Vector3<f32>,
}
unsafe impl bytemuck::Pod for Vertex {}
unsafe impl bytemuck::Zeroable for Vertex {}
impl Vertex {
pub fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
wgpu::VertexBufferDescriptor {
stride: size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &wgpu::vertex_attr_array!(
0 => Float4
),
}
}
}
fn vertex(x: f32, y: f32, z: f32) -> Vertex {
Vertex {
position: Vector3 { x, y, z },
}
}
pub struct Mesh {
pub index_count: u32,
pub index_buffer: wgpu::Buffer,
pub vertex_buffer: wgpu::Buffer,
}
impl Mesh {
pub fn axes(device: &wgpu::Device) -> Self {
let axes_vertices: &[Vertex] = &[
vertex(0.0, 0.0, 0.0),
vertex(1000.0, 0.0, 0.0),
vertex(0.0, 1000.0, 0.0),
vertex(0.0, 0.0, 1000.0),
];
let axes_indices: &[u16] = &[0, 1, 0, 2, 0, 3];
let index_count = axes_indices.len() as u32;
let index_buffer = device
.create_buffer_with_data(bytemuck::cast_slice(axes_indices), wgpu::BufferUsage::INDEX);
let vertex_buffer = device.create_buffer_with_data(
bytemuck::cast_slice(axes_vertices),
wgpu::BufferUsage::VERTEX,
);
Self {
index_count,
index_buffer,
vertex_buffer,
}
}
}

@ -1,8 +0,0 @@
#version 450
layout(location=0) in vec3 vPosition;
layout(location=0) out vec4 fColor;
void main() {
fColor = vec4(vPosition, 1);
}

@ -1,15 +0,0 @@
#version 450
layout(location=0) in vec3 aPosition;
layout(location=0) out vec3 vPosition;
layout(set=0, binding=0) uniform Uniforms {
mat4 projectionMatrix;
mat4 viewMatrix;
mat4 viewProjectionMatrix;
} ubo;
void main() {
vPosition = aPosition;
gl_Position = ubo.viewProjectionMatrix * vec4(aPosition, 1);
}

@ -1,7 +0,0 @@
#version 450
layout(location = 0) out vec4 f_Color;
void main() {
f_Color = vec4(1, 1, 0, 1);
}

@ -1,196 +0,0 @@
use cgmath::*;
use std::time::Duration;
use winit::dpi::*;
use winit::event::*;
use winit::window::Window;
use crate::camera::*;
use crate::data::*;
use crate::pipeline::*;
use crate::resource::*;
pub struct Demo {
surface: wgpu::Surface,
#[allow(dead_code)]
adapter: wgpu::Adapter,
device: wgpu::Device,
queue: wgpu::Queue,
sc_desc: wgpu::SwapChainDescriptor,
swap_chain: wgpu::SwapChain,
debug_pipeline: wgpu::RenderPipeline,
// other resources
axes: Mesh,
clear_color: wgpu::Color,
pub is_running: bool,
camera: Camera,
controller: CameraController,
projection: Projection,
uniforms: Uniforms,
uniforms_bind_group: wgpu::BindGroup,
last_mouse_pos: PhysicalPosition<f64>,
mouse_pressed: bool,
}
impl Demo {
pub async fn new(window: &Window) -> Self {
let surface = wgpu::Surface::create(window);
let adapter: wgpu::Adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
compatible_surface: Some(&surface),
},
wgpu::BackendBit::PRIMARY,
)
.await
.unwrap();
let (device, queue): (wgpu::Device, wgpu::Queue) =
adapter.request_device(&Default::default()).await;
let inner_size = window.inner_size();
let sc_desc = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
width: inner_size.width,
height: inner_size.height,
present_mode: wgpu::PresentMode::Fifo,
};
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
let camera = Camera::new((0.0, 0.5, 3.0), Deg(-90.0), Deg(0.0));
let controller = CameraController::new(0.5);
let projection =
Projection::new(inner_size.width, inner_size.height, Deg(45.0), 0.1, 1000.0);
let uniforms = Uniforms::new(&device, &camera, &projection);
let (uniform_layout, uniforms_bind_group) = create_uniform_binding(&device, &uniforms);
let debug_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&uniform_layout],
});
let debug_pipeline = RenderPipelineBuilder::new()
.layout(&debug_pipeline_layout)
.color_solid(sc_desc.format)
.primitive_topology(wgpu::PrimitiveTopology::LineList)
.vertex_shader(include_bytes!("debug.vert.spv"))
.fragment_shader(include_bytes!("debug.frag.spv"))
.index_format(wgpu::IndexFormat::Uint16)
.vertex_buffer(Vertex::desc())
.cull_mode(wgpu::CullMode::None)
.build(&device)
.unwrap();
let axes = Mesh::axes(&device);
Self {
surface,
adapter,
device,
queue,
sc_desc,
swap_chain,
debug_pipeline,
axes,
clear_color: wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
},
is_running: true,
camera,
controller,
projection,
uniforms,
uniforms_bind_group,
last_mouse_pos: (0.0, 0.0).into(),
mouse_pressed: false,
}
}
pub fn resize(&mut self, new_size: PhysicalSize<u32>) {
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.projection.resize(new_size.width, new_size.height);
self.uniforms.apply_projection(&self.projection);
}
pub fn input(&mut self, event: &WindowEvent) -> bool {
match event {
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => {
self.controller.process_keyboard(*key, *state)
|| match (key, *state == ElementState::Pressed) {
(VirtualKeyCode::Escape, true) => {
self.is_running = false;
true
}
_ => false,
}
}
WindowEvent::MouseInput {
button: MouseButton::Left,
state,
..
} => {
self.mouse_pressed = *state == ElementState::Pressed;
true
}
WindowEvent::CursorMoved { position, .. } => {
let mouse_dx = position.x - self.last_mouse_pos.x;
let mouse_dy = position.y - self.last_mouse_pos.y;
self.last_mouse_pos = *position;
if self.mouse_pressed {
self.controller.process_mouse(mouse_dx, mouse_dy);
true
} else {
false
}
}
_ => false,
}
}
pub fn update(&mut self, dt: Duration) {
if self.controller.is_dirty() {
self.controller.update_camera(&mut self.camera, dt);
self.uniforms.apply_camera(&self.camera);
}
if let Some(cmds) = self.uniforms.update(&self.device) {
self.queue.submit(&[cmds]);
}
}
pub fn render(&mut self) {
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
let frame = self
.swap_chain
.get_next_texture()
.expect("Unable to retrieve swap chain texture");
{
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: self.clear_color,
}],
depth_stencil_attachment: None,
});
pass.set_pipeline(&self.debug_pipeline);
pass.set_bind_group(0, &self.uniforms_bind_group, &[]);
pass.set_index_buffer(&self.axes.index_buffer, 0, 0);
pass.set_vertex_buffer(0, &self.axes.vertex_buffer, 0, 0);
pass.draw_indexed(0..self.axes.index_count, 0, 0..1);
}
self.queue.submit(&[encoder.finish()]);
}
}

@ -1,71 +0,0 @@
mod camera;
mod data;
mod demo;
mod pipeline;
mod resource;
use demo::*;
use winit::dpi::*;
use winit::event::*;
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::*;
use futures::executor::block_on;
use std::time::Instant;
fn main() {
env_logger::init();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
.with_inner_size(PhysicalSize::new(800, 600))
.with_title(env!("CARGO_PKG_NAME"))
.build(&event_loop)
.unwrap();
let mut demo = block_on(Demo::new(&window));
let mut last_update = Instant::now();
let mut is_focused = false;
event_loop.run(move |event, _, control_flow| {
*control_flow = if is_focused {
ControlFlow::Poll
} else if demo.is_running {
ControlFlow::Wait
} else {
ControlFlow::Exit
};
match event {
Event::MainEventsCleared => {
if is_focused {
window.request_redraw();
}
}
Event::WindowEvent {
ref event,
window_id,
} => {
if window_id == window.id() && !demo.input(event) {
match event {
WindowEvent::Focused(f) => is_focused = *f,
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
demo.resize(**new_inner_size)
}
WindowEvent::Resized(new_size) => demo.resize(*new_size),
_ => {}
}
}
}
Event::RedrawRequested(window_id) => {
if window_id == window.id() {
let now = Instant::now();
let dt = now - last_update;
last_update = now;
demo.update(dt);
demo.render();
}
}
_ => {}
}
});
}

@ -1,231 +0,0 @@
use failure::bail;
pub struct RenderPipelineBuilder<'a> {
layout: Option<&'a wgpu::PipelineLayout>,
vertex_shader: Option<&'a [u8]>,
fragment_shader: Option<&'a [u8]>,
front_face: wgpu::FrontFace,
cull_mode: wgpu::CullMode,
depth_bias: i32,
depth_bias_slope_scale: f32,
depth_bias_clamp: f32,
primitive_topology: wgpu::PrimitiveTopology,
color_states: Vec<wgpu::ColorStateDescriptor>,
depth_stencil_state: Option<wgpu::DepthStencilStateDescriptor>,
index_format: wgpu::IndexFormat,
vertex_buffers: Vec<wgpu::VertexBufferDescriptor<'a>>,
sample_count: u32,
sample_mask: u32,
alpha_to_coverage_enabled: bool,
}
impl<'a> RenderPipelineBuilder<'a> {
pub fn new() -> Self {
Self {
layout: None,
vertex_shader: None,
fragment_shader: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::None,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: Vec::new(),
depth_stencil_state: None,
index_format: wgpu::IndexFormat::Uint32,
vertex_buffers: Vec::new(),
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
}
}
pub fn layout(&mut self, layout: &'a wgpu::PipelineLayout) -> &mut Self {
self.layout = Some(layout);
self
}
pub fn vertex_shader(&mut self, spv: &'a [u8]) -> &mut Self {
self.vertex_shader = Some(spv);
self
}
pub fn fragment_shader(&mut self, spv: &'a [u8]) -> &mut Self {
self.fragment_shader = Some(spv);
self
}
#[allow(dead_code)]
pub fn front_face(&mut self, ff: wgpu::FrontFace) -> &mut Self {
self.front_face = ff;
self
}
#[allow(dead_code)]
pub fn cull_mode(&mut self, cm: wgpu::CullMode) -> &mut Self {
self.cull_mode = cm;
self
}
#[allow(dead_code)]
pub fn depth_bias(&mut self, db: i32) -> &mut Self {
self.depth_bias = db;
self
}
#[allow(dead_code)]
pub fn depth_bias_slope_scale(&mut self, dbss: f32) -> &mut Self {
self.depth_bias_slope_scale = dbss;
self
}
#[allow(dead_code)]
pub fn depth_bias_clamp(&mut self, dbc: f32) -> &mut Self {
self.depth_bias_clamp = dbc;
self
}
#[allow(dead_code)]
pub fn primitive_topology(&mut self, pt: wgpu::PrimitiveTopology) -> &mut Self {
self.primitive_topology = pt;
self
}
pub fn color_state(&mut self, cs: wgpu::ColorStateDescriptor) -> &mut Self {
self.color_states.push(cs);
self
}
/// Helper method for [RenderPipelineBuilder::color_state]
pub fn color_solid(&mut self, format: wgpu::TextureFormat) -> &mut Self {
self.color_state(wgpu::ColorStateDescriptor {
format,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
color_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
})
}
pub fn depth_stencil_state(&mut self, dss: wgpu::DepthStencilStateDescriptor) -> &mut Self {
self.depth_stencil_state = Some(dss);
self
}
/// Helper method for [RenderPipelineBuilder::depth_stencil_state]
pub fn depth_no_stencil(
&mut self,
format: wgpu::TextureFormat,
depth_write_enabled: bool,
depth_compare: wgpu::CompareFunction,
) -> &mut Self {
self.depth_stencil_state(wgpu::DepthStencilStateDescriptor {
format,
depth_write_enabled,
depth_compare,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
})
}
/// Helper method for [RenderPipelineBuilder::depth_no_stencil]
#[allow(dead_code)]
pub fn depth_format(&mut self, format: wgpu::TextureFormat) -> &mut Self {
self.depth_no_stencil(format, true, wgpu::CompareFunction::Less)
}
#[allow(dead_code)]
pub fn index_format(&mut self, ifmt: wgpu::IndexFormat) -> &mut Self {
self.index_format = ifmt;
self
}
pub fn vertex_buffer(&mut self, vb: wgpu::VertexBufferDescriptor<'a>) -> &mut Self {
self.vertex_buffers.push(vb);
self
}
#[allow(dead_code)]
pub fn sample_count(&mut self, sc: u32) -> &mut Self {
self.sample_count = sc;
self
}
#[allow(dead_code)]
pub fn sample_mask(&mut self, sm: u32) -> &mut Self {
self.sample_mask = sm;
self
}
#[allow(dead_code)]
pub fn alpha_to_coverage_enabled(&mut self, atce: bool) -> &mut Self {
self.alpha_to_coverage_enabled = atce;
self
}
pub fn build(&self, device: &wgpu::Device) -> Result<wgpu::RenderPipeline, failure::Error> {
// We need a layout
if self.layout.is_none() {
bail!("No pipeline layout supplied!");
}
let layout = self.layout.unwrap();
// Render pipelines always have a vertex shader, but due
// to the way the builder pattern works, we can't
// guarantee that the user will specify one, so we'll
// just return an error if they forgot.
//
// We could supply a default one, but a "default" vertex
// could take on many forms. An error is much more
// explicit.
if self.vertex_shader.is_none() {
bail!("No vertex shader supplied!")
}
let vs = create_shader_module(device, self.vertex_shader.unwrap());
// The fragment shader is optional (IDK why, but it is).
// Having the shader be optional is giving me issues with
// the borrow checker so I'm going to use a default shader
// if the user doesn't supply one.
let fs_spv = self
.fragment_shader
.unwrap_or(include_bytes!("default.frag.spv"));
let fs = create_shader_module(device, fs_spv);
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
layout: &layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: self.front_face,
cull_mode: self.cull_mode,
depth_bias: self.depth_bias,
depth_bias_slope_scale: self.depth_bias_slope_scale,
depth_bias_clamp: self.depth_bias_clamp,
}),
primitive_topology: self.primitive_topology,
color_states: &self.color_states,
depth_stencil_state: self.depth_stencil_state.clone(),
vertex_state: wgpu::VertexStateDescriptor {
index_format: self.index_format,
vertex_buffers: &self.vertex_buffers,
},
sample_count: self.sample_count,
sample_mask: self.sample_mask,
alpha_to_coverage_enabled: self.alpha_to_coverage_enabled,
});
Ok(pipeline)
}
}
fn create_shader_module(device: &wgpu::Device, spirv: &[u8]) -> wgpu::ShaderModule {
device.create_shader_module(&wgpu::read_spirv(std::io::Cursor::new(spirv)).unwrap())
}

@ -1,106 +0,0 @@
use cgmath::*;
use crate::camera::*;
use std::mem::size_of;
#[derive(Debug)]
pub struct Uniforms {
raw: UniformsRaw,
buffer: wgpu::Buffer,
dirty: bool,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
struct UniformsRaw {
projection_matrix: Matrix4<f32>,
view_matrix: Matrix4<f32>,
view_proj_matrix: Matrix4<f32>,
}
unsafe impl bytemuck::Pod for UniformsRaw {}
unsafe impl bytemuck::Zeroable for UniformsRaw {}
impl Uniforms {
pub fn new(device: &wgpu::Device, camera: &Camera, projection: &Projection) -> Self {
let projection_matrix = projection.calc_matrix();
let view_matrix = camera.calc_matrix();
let raw = UniformsRaw {
projection_matrix,
view_matrix,
view_proj_matrix: projection_matrix * view_matrix,
};
let buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&[raw]),
wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM,
);
Self {
raw,
buffer,
dirty: true,
}
}
pub fn apply_camera(&mut self, camera: &Camera) {
self.raw.view_matrix = camera.calc_matrix();
self.dirty = true;
}
pub fn apply_projection(&mut self, projection: &Projection) {
self.raw.projection_matrix = projection.calc_matrix();
self.dirty = true;
}
pub fn update(&mut self, device: &wgpu::Device) -> Option<wgpu::CommandBuffer> {
if self.dirty {
self.dirty = false;
self.raw.view_proj_matrix = self.raw.projection_matrix * self.raw.view_matrix;
let copy_buffer = device.create_buffer_with_data(
bytemuck::cast_slice(&[self.raw]),
wgpu::BufferUsage::COPY_SRC,
);
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Uniforms::update()"),
});
encoder.copy_buffer_to_buffer(
&copy_buffer,
0,
&self.buffer,
0,
size_of::<UniformsRaw>() as wgpu::BufferAddress,
);
Some(encoder.finish())
} else {
None
}
}
}
pub fn create_uniform_binding(
device: &wgpu::Device,
uniforms: &Uniforms,
) -> (wgpu::BindGroupLayout, wgpu::BindGroup) {
let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Uniforms::BindGroupLayout"),
bindings: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
}],
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Uniforms::BindGroup"),
layout: &layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniforms.buffer,
range: 0..size_of::<UniformsRaw>() as wgpu::BufferAddress,
},
}],
});
(layout, bind_group)
}

@ -1,11 +0,0 @@
#version 450
const vec2 positions[3] = vec2[3](
vec2(0.0, 0.5),
vec2(-0.5, -0.5),
vec2(0.5, -0.5)
);
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
}

@ -19,7 +19,7 @@ fn copy_res() {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options).unwrap();
}

@ -85,7 +85,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -85,7 +85,7 @@ fn main() -> Result<()> {
// let mut copy_options = CopyOptions::new();
// copy_options.overwrite = true;
// let mut paths_to_copy = Vec::new();
// paths_to_copy.push("./res/");
// paths_to_copy.push("res/");
// copy_items(&paths_to_copy, out_dir, &copy_options)?;
Ok(())

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
match copy_items(&paths_to_copy, out_dir, &copy_options) {
Ok(_) => {}
Err(e) => eprintln!("{}", e),

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
match copy_items(&paths_to_copy, out_dir, &copy_options) {
Ok(_) => {}
Err(e) => println!("{}", e),

@ -87,7 +87,7 @@ fn main() -> Result<()> {
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
match copy_items(&paths_to_copy, out_dir, &copy_options) {
Ok(_) => {}
Err(e) => eprintln!("{}", e),

@ -76,7 +76,7 @@ let out_dir = env::var("OUT_DIR")?;
let mut copy_options = CopyOptions::new();
copy_options.overwrite = true;
let mut paths_to_copy = Vec::new();
paths_to_copy.push("./res/");
paths_to_copy.push("res/");
copy_items(&paths_to_copy, out_dir, &copy_options)?;
```

Loading…
Cancel
Save