master
mitchellhansen 4 years ago
parent 77dcf1faf9
commit 9ebaece426

File diff suppressed because it is too large Load Diff

@ -0,0 +1,10 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 0
Ka 0.000000 0.000000 0.000000
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

File diff suppressed because it is too large Load Diff

@ -2,7 +2,7 @@ use bytemuck::{Pod, Zeroable};
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
struct Vertex { pub struct Vertex {
_pos: [f32; 4], _pos: [f32; 4],
_normal: [f32; 4], _normal: [f32; 4],
} }
@ -11,14 +11,14 @@ unsafe impl Pod for Vertex {}
unsafe impl Zeroable for Vertex {} unsafe impl Zeroable for Vertex {}
fn vertex(pos: [f32; 3], nor: [f32; 3]) -> Vertex { pub fn vertex(pos: [f32; 3], nor: [f32; 3]) -> Vertex {
Vertex { Vertex {
_pos: [pos[0], pos[1], pos[2], 1.0], _pos: [pos[0], pos[1], pos[2], 1.0],
_normal: [nor[0], nor[1], nor[2], 0.0], _normal: [nor[0], nor[1], nor[2], 0.0],
} }
} }
fn import_mesh(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) { pub fn import_mesh(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) {
//let obj_file = "/home/mrh/source/3d-min-viable-eng/resources/Tree_01.obj"; //let obj_file = "/home/mrh/source/3d-min-viable-eng/resources/Tree_01.obj";
//let mtl_file = "/home/mrh/source/3d-min-viable-eng/resources/Tree_01.mtl"; //let mtl_file = "/home/mrh/source/3d-min-viable-eng/resources/Tree_01.mtl";
let (models, materials) = tobj::load_obj(mesh_path, false).expect("Failed to load file"); let (models, materials) = tobj::load_obj(mesh_path, false).expect("Failed to load file");
@ -73,7 +73,7 @@ fn import_mesh(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) {
} }
fn create_plane(size: f32) -> (Vec<Vertex>, Vec<u32>) { pub fn create_plane(size: f32) -> (Vec<Vertex>, Vec<u32>) {
let vertex_data = [ let vertex_data = [
vertex([size, -size, 0.0], [0.0, 0.0, 1.0]), vertex([size, -size, 0.0], [0.0, 0.0, 1.0]),
vertex([size, size, 0.0], [0.0, 0.0, 1.0]), vertex([size, size, 0.0], [0.0, 0.0, 1.0]),

@ -1,7 +1,8 @@
use bytemuck::__core::ops::Range; use bytemuck::__core::ops::Range;
use bytemuck::{Zeroable, Pod}; use bytemuck::{Zeroable, Pod};
use crate::OPENGL_TO_WGPU_MATRIX;
struct Light { pub struct Light {
pos: cgmath::Point3<f32>, pos: cgmath::Point3<f32>,
color: wgpu::Color, color: wgpu::Color,
fov: f32, fov: f32,
@ -11,7 +12,7 @@ struct Light {
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct LightRaw { pub struct LightRaw {
proj: [[f32; 4]; 4], proj: [[f32; 4]; 4],
pos: [f32; 4], pos: [f32; 4],
color: [f32; 4], color: [f32; 4],
@ -32,7 +33,7 @@ impl Light {
near: self.depth.start, near: self.depth.start,
far: self.depth.end, far: self.depth.end,
}; };
let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; let mx_correction = OPENGL_TO_WGPU_MATRIX;
let mx_view_proj = let mx_view_proj =
mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
LightRaw { LightRaw {

@ -13,6 +13,7 @@ use winit::{
event::{self, WindowEvent}, event::{self, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
}; };
use crate::render::Renderer;
mod framework; mod framework;
mod geometry; mod geometry;
@ -130,8 +131,9 @@ fn main() {
.await .await
.unwrap(); .unwrap();
let optional_features = E::optional_features();
let required_features = E::required_features(); let optional_features = Renderer::optional_features();
let required_features = Renderer::required_features();
let adapter_features = adapter.features(); let adapter_features = adapter.features();
assert!( assert!(
adapter_features.contains(required_features), adapter_features.contains(required_features),
@ -139,7 +141,7 @@ fn main() {
required_features - adapter_features required_features - adapter_features
); );
let needed_limits = E::required_limits(); let needed_limits = wgpu::Limits::default();//Renderer::required_limits();
// Maybe for debug tracing??? // Maybe for debug tracing???
let trace_dir = std::env::var("WGPU_TRACE"); let trace_dir = std::env::var("WGPU_TRACE");
@ -196,7 +198,7 @@ fn main() {
WebSpawner {} WebSpawner {}
};*/ };*/
// Swapchain has a prototype dealio
let mut sc_desc = wgpu::SwapChainDescriptor { let mut sc_desc = wgpu::SwapChainDescriptor {
// Allows a texture to be a output attachment of a renderpass. // Allows a texture to be a output attachment of a renderpass.
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT, usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
@ -224,6 +226,8 @@ fn main() {
log::info!("Entering render loop..."); log::info!("Entering render loop...");
let mut renderer = render::Renderer::init();
// This is just an winit event loop // This is just an winit event loop
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
@ -271,7 +275,7 @@ fn main() {
sc_desc.width = size.width; sc_desc.width = size.width;
sc_desc.height = size.height; sc_desc.height = size.height;
example.resize(&sc_desc, &device, &queue); renderer.resize(&sc_desc, &device, &queue);
swap_chain = device.create_swap_chain(&surface, &sc_desc); swap_chain = device.create_swap_chain(&surface, &sc_desc);
} }
@ -289,7 +293,7 @@ fn main() {
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
_ => { _ => {
example.update(event); renderer.update(event);
} }
}, },
event::Event::RedrawRequested(_) => { event::Event::RedrawRequested(_) => {
@ -303,7 +307,7 @@ fn main() {
} }
}; };
example.render(&frame.output, &device, &queue, &spawner); renderer.render(&frame.output, &device, &queue, &spawner);
} }
_ => {} _ => {}
} }

@ -1,12 +1,15 @@
use crate::{EntityUniforms, Pass};
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use bytemuck::__core::mem; use bytemuck::__core::mem;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use std::rc::Rc; use std::{iter, num::NonZeroU32, ops::Range, rc::Rc};
use crate::OPENGL_TO_WGPU_MATRIX;
use crate::light::LightRaw;
use crate::geometry::{Vertex, import_mesh, create_plane};
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct ForwardUniforms { pub struct ForwardUniforms {
proj: [[f32; 4]; 4], proj: [[f32; 4]; 4],
num_lights: [u32; 4], num_lights: [u32; 4],
} }
@ -17,7 +20,7 @@ unsafe impl Zeroable for ForwardUniforms {}
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct EntityUniforms { pub struct EntityUniforms {
model: [[f32; 4]; 4], model: [[f32; 4]; 4],
color: [f32; 4], color: [f32; 4],
} }
@ -27,17 +30,16 @@ unsafe impl Pod for EntityUniforms {}
unsafe impl Zeroable for EntityUniforms {} unsafe impl Zeroable for EntityUniforms {}
#[repr(C)] #[repr(C)]
struct ShadowUniforms { pub struct ShadowUniforms {
proj: [[f32; 4]; 4], proj: [[f32; 4]; 4],
} }
struct Pass { pub struct Pass {
pipeline: wgpu::RenderPipeline, pipeline: wgpu::RenderPipeline,
bind_group: wgpu::BindGroup, bind_group: wgpu::BindGroup,
uniform_buf: wgpu::Buffer, uniform_buf: wgpu::Buffer,
} }
pub struct Renderer { pub struct Renderer {
lights_are_dirty: bool, lights_are_dirty: bool,
shadow_pass: Pass, shadow_pass: Pass,
@ -63,7 +65,7 @@ impl Renderer {
cgmath::Point3::new(0f32, 0.0, 0.0), cgmath::Point3::new(0f32, 0.0, 0.0),
cgmath::Vector3::unit_z(), cgmath::Vector3::unit_z(),
); );
let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; let mx_correction = OPENGL_TO_WGPU_MATRIX;
mx_correction * mx_projection * mx_view mx_correction * mx_projection * mx_view
} }
} }
@ -115,7 +117,7 @@ impl Renderer {
}); });
} }
pub fn init(&mut self) -> Renderer { pub fn init(device: &wgpu::Device) -> Renderer {
// Pre init the light uniform, with slots enough for MAX_LIGHTS // Pre init the light uniform, with slots enough for MAX_LIGHTS
let light_uniform_size = let light_uniform_size =
@ -133,6 +135,7 @@ impl Renderer {
// This seems way way way way easier than what I was doing in tracer // This seems way way way way easier than what I was doing in tracer
// Though the attr thing is still a macro. Which would cause issues if // Though the attr thing is still a macro. Which would cause issues if
// I wanted to get tricky with the 0,1 types // I wanted to get tricky with the 0,1 types
let vertex_size = mem::size_of::<Vertex>();
let vertex_attr = wgpu::vertex_attr_array![0 => Float4, 1 => Float4]; let vertex_attr = wgpu::vertex_attr_array![0 => Float4, 1 => Float4];
let vb_desc = wgpu::VertexBufferDescriptor { let vb_desc = wgpu::VertexBufferDescriptor {
stride: vertex_size as wgpu::BufferAddress, stride: vertex_size as wgpu::BufferAddress,
@ -140,6 +143,24 @@ impl Renderer {
attributes: &vertex_attr, attributes: &vertex_attr,
}; };
// This is also in the runtime which really shouldn't have this
let local_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
count: None,
ty: wgpu::BindingType::UniformBuffer {
dynamic: false,
min_binding_size: wgpu::BufferSize::new(
mem::size_of::<EntityUniforms>() as _
),
},
}],
});
/* /*
There appear to be two passes required for shadows, the shadow pass, and the forward pass There appear to be two passes required for shadows, the shadow pass, and the forward pass
Need to open this up in renderdoc and see what it's actually doing Need to open this up in renderdoc and see what it's actually doing
@ -147,7 +168,8 @@ impl Renderer {
let shadow_pass = { let shadow_pass = {
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress; let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
// Create pipeline layout
// I believe this is just making a_Pos or u_ViewProj available in the vert shader
let bind_group_layout = let bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None, label: None,
@ -161,12 +183,15 @@ impl Renderer {
count: None, count: None,
}], }],
}); });
// Pipeline is similar between passes, but with a different label
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("shadow"), label: Some("shadow"),
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
// Holds the shadow uniforms, which is just a 4 vec of quaternians
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: None, label: None,
size: uniform_size, size: uniform_size,
@ -276,6 +301,7 @@ impl Renderer {
], ],
label: None, label: None,
}); });
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("main"), label: Some("main"),
bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout], bind_group_layouts: &[&bind_group_layout, &local_bind_group_layout],

@ -1,21 +1,31 @@
use crate::ShadowUniforms;
use bytemuck::__core::mem;
use std::rc::Rc; use std::rc::Rc;
use bytemuck::__core::mem;
use crate::light::Light;
use crate::render::EntityUniforms;
/*
This will eventually be within an ECS...
So I will probably take the same approach that I did for tracer and have meta-data for rendering
held by the ECS, and a render system which will cycle through them and render
*/
struct Entity { struct Entity {
mx_world: cgmath::Matrix4<f32>, mx_world: cgmath::Matrix4<f32>,
rotation_speed: f32, rotation_speed: f32,
color: wgpu::Color, color: wgpu::Color,
vertex_buf: Rc<wgpu::Buffer>, vertex_buf: Rc<wgpu::Buffer>, // Could probably tie this along with index & count to some resource handle in the renderer
index_buf: Rc<wgpu::Buffer>, index_buf: Rc<wgpu::Buffer>,
index_count: usize, index_count: usize,
bind_group: wgpu::BindGroup, bind_group: wgpu::BindGroup, // This is a little weird to have in the entity isn't it?
uniform_buf: wgpu::Buffer, uniform_buf: wgpu::Buffer,
} }
pub struct Runtime { pub struct Runtime {
entities: Vec<Entity>, // This is going to be ECS'd entities: Vec<Entity>,
// This is going to be ECS'd
lights: Vec<Light>, // ECS lights: Vec<Light>, // ECS
} }
@ -27,8 +37,31 @@ impl Runtime {
{ {
// https://sotrh.github.io/learn-wgpu/beginner/tutorial5-textures/#the-bindgroup // https://sotrh.github.io/learn-wgpu/beginner/tutorial5-textures/#the-bindgroup
// It appears like bindgroups are // It appears like bindgroups are the shader input definitions
/*
But it is defined in multiples places...
` `
one of these in each pass
let bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
The entities have one
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &local_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(plane_uniform_buf.slice(..)),
}],
label: None,
});
*/
// Defines the Uniform buffer for the Vertex and Fragment shaders // Defines the Uniform buffer for the Vertex and Fragment shaders
let local_bind_group_layout = let local_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {

Loading…
Cancel
Save