Houstin, we have rendering.

master
mitchellhansen 4 years ago
parent 60a950abe2
commit 80ac21e9d3

@ -1,25 +1,24 @@
extern crate tobj; extern crate tobj;
extern crate winit; extern crate winit;
use std::rc::Rc;
use std::sync::Arc;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use bytemuck::__core::ops::Range;
use cgmath::{Matrix4, Point3};
use futures::task::LocalSpawn; use futures::task::LocalSpawn;
use legion::*;
use wgpu::{BindGroup, Buffer};
use wgpu_subscriber; use wgpu_subscriber;
use winit::platform::unix::x11::ffi::Time;
use winit::{ use winit::{
event::{self, WindowEvent}, event::{self, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
}; };
use crate::render::Renderer; use crate::render::Renderer;
use bytemuck::__core::ops::Range;
use cgmath::{Point3, Matrix4};
use std::rc::Rc;
use wgpu::Buffer;
use winit::platform::unix::x11::ffi::Time;
use legion::*;
use std::sync::Arc;
mod framework; mod framework;
mod geometry; mod geometry;
@ -56,7 +55,6 @@ ECS
*/ */
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
#[allow(unused)] #[allow(unused)]
pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new( pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4<f32> = cgmath::Matrix4::new(
@ -125,19 +123,20 @@ pub struct RangeCopy<Idx> {
struct DirectionalLight { struct DirectionalLight {
color: wgpu::Color, color: wgpu::Color,
fov: f32, fov: f32,
depth: RangeCopy<f32> depth: RangeCopy<f32>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Mesh { pub struct Mesh {
index_buffer: Arc<Buffer>, index_buffer: Arc<Buffer>,
index_count: usize,
vertex_buffer: Arc<Buffer>, vertex_buffer: Arc<Buffer>,
uniform_buf: Arc<Buffer>, uniform_buffer: Arc<Buffer>,
bind_group: Arc<BindGroup>,
} }
fn main() {
fn main() {
// #[cfg(not(target_arch = "wasm32"))] // #[cfg(not(target_arch = "wasm32"))]
// { // {
// let chrome_tracing_dir = std::env::var("WGPU_CHROME_TRACE"); // let chrome_tracing_dir = std::env::var("WGPU_CHROME_TRACE");
@ -205,7 +204,6 @@ fn main() {
let window = builder.build(&event_loop).unwrap(); let window = builder.build(&event_loop).unwrap();
// Not sure why this is guarded, maybe we don't handle the event loop timing? // Not sure why this is guarded, maybe we don't handle the event loop timing?
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let mut last_update_inst = Instant::now(); let mut last_update_inst = Instant::now();
@ -215,7 +213,8 @@ fn main() {
// Load up the renderer (and the resources) // Load up the renderer (and the resources)
let mut renderer = render::Renderer::init(window); let mut renderer = render::Renderer::init(window);
let (plane_vertex_buffer, plane_index_buffer, plane_uniform_buffer) = renderer.load_mesh_to_buffer("./resources/untitled.obj"); let untitled_mesh =
renderer.load_mesh_to_buffer("./resources/untitled.obj");
// This could be used for relationships between entities...??? // This could be used for relationships between entities...???
let light_entity: Entity = world.push(( let light_entity: Entity = world.push((
@ -232,8 +231,11 @@ fn main() {
a: 1.0, a: 1.0,
}, },
fov: 45.0, fov: 45.0,
depth: RangeCopy { start: 1.0, end: 20.0 }, depth: RangeCopy {
} start: 1.0,
end: 20.0,
},
},
)); ));
let mesh_entity: Entity = world.push(( let mesh_entity: Entity = world.push((
@ -241,13 +243,9 @@ fn main() {
x: -5.0, x: -5.0,
y: 7.0, y: 7.0,
z: 10.0, z: 10.0,
mx: OPENGL_TO_WGPU_MATRIX mx: OPENGL_TO_WGPU_MATRIX,
},
Mesh {
index_buffer: plane_index_buffer,
vertex_buffer: plane_vertex_buffer,
uniform_buf: plane_uniform_buffer,
}, },
untitled_mesh,
Color { Color {
r: 1.0, r: 1.0,
g: 0.5, g: 0.5,
@ -257,9 +255,45 @@ fn main() {
)); ));
let entities: &[Entity] = world.extend(vec![ let entities: &[Entity] = world.extend(vec![
(Position { x: 0.0, y: 0.0, z: 0.0, mx: OPENGL_TO_WGPU_MATRIX }, Velocity { dx: 0.0, dy: 0.0, rs: 0.0 }), (
(Position { x: 1.0, y: 1.0, z: 0.0, mx: OPENGL_TO_WGPU_MATRIX }, Velocity { dx: 0.0, dy: 0.0, rs: 0.0 }), Position {
(Position { x: 2.0, y: 2.0, z: 0.0, mx: OPENGL_TO_WGPU_MATRIX }, Velocity { dx: 0.0, dy: 0.0, rs: 0.0 }), x: 0.0,
y: 0.0,
z: 0.0,
mx: OPENGL_TO_WGPU_MATRIX,
},
Velocity {
dx: 0.0,
dy: 0.0,
rs: 0.0,
},
),
(
Position {
x: 1.0,
y: 1.0,
z: 0.0,
mx: OPENGL_TO_WGPU_MATRIX,
},
Velocity {
dx: 0.0,
dy: 0.0,
rs: 0.0,
},
),
(
Position {
x: 2.0,
y: 2.0,
z: 0.0,
mx: OPENGL_TO_WGPU_MATRIX,
},
Velocity {
dx: 0.0,
dy: 0.0,
rs: 0.0,
},
),
]); ]);
// Init, this wants the references to the buffers... // Init, this wants the references to the buffers...
@ -296,7 +330,11 @@ fn main() {
// ask for a redraw every 20 millis // ask for a redraw every 20 millis
if last_update_inst.elapsed() > Duration::from_millis(20) { if last_update_inst.elapsed() > Duration::from_millis(20) {
//window.request_redraw(); //window.request_redraw();
resources.get_mut::<Renderer>().unwrap().window.request_redraw(); resources
.get_mut::<Renderer>()
.unwrap()
.window
.request_redraw();
last_update_inst = Instant::now(); last_update_inst = Instant::now();
} }
@ -316,7 +354,10 @@ fn main() {
let width = size.width; let width = size.width;
let height = size.height; let height = size.height;
resources.get_mut::<Renderer>().unwrap().resize(width, height); resources
.get_mut::<Renderer>()
.unwrap()
.resize(width, height);
//swap_chain = device.create_swap_chain(&surface, &sc_desc); //swap_chain = device.create_swap_chain(&surface, &sc_desc);
} }
@ -338,15 +379,10 @@ fn main() {
} }
}, },
event::Event::RedrawRequested(_) => { event::Event::RedrawRequested(_) => {
render_schedule.execute(&mut world, &mut resources); render_schedule.execute(&mut world, &mut resources);
//resources.get_mut::<Renderer>().unwrap().render(); //resources.get_mut::<Renderer>().unwrap().render();
} }
_ => {} _ => {}
} }
}); });
} }

@ -3,19 +3,19 @@ use std::{iter, num::NonZeroU32, ops::Range, rc::Rc};
use bytemuck::__core::mem; use bytemuck::__core::mem;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use cgmath::Point3;
use futures::executor::LocalPool;
use legion::world::SubWorld;
use legion::*; use legion::*;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use wgpu::{Buffer, Device, SwapChain, Queue, SwapChainFrame, Surface, SwapChainDescriptor, Instance}; use wgpu::{Buffer, Device, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, BindGroup, BindGroupLayout};
use winit::dpi::{PhysicalSize}; use winit::dpi::PhysicalSize;
use winit::platform::unix::x11::ffi::Time; use winit::platform::unix::x11::ffi::Time;
use winit::window::Window; use winit::window::Window;
use crate::geometry::{create_plane, import_mesh, Vertex}; use crate::geometry::{create_plane, import_mesh, Vertex};
use crate::light::LightRaw; use crate::light::LightRaw;
use crate::{Velocity, OPENGL_TO_WGPU_MATRIX, Color, Mesh, Position}; use crate::{Color, Mesh, Position, Velocity, OPENGL_TO_WGPU_MATRIX};
use futures::executor::LocalPool;
use legion::world::SubWorld;
use cgmath::Point3;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -65,11 +65,10 @@ pub struct Renderer {
shadow_pass: Pass, shadow_pass: Pass,
forward_pass: Pass, forward_pass: Pass,
forward_depth: wgpu::TextureView, forward_depth: wgpu::TextureView,
entity_bind_group_layout: BindGroupLayout,
light_uniform_buf: wgpu::Buffer, light_uniform_buf: wgpu::Buffer,
// plane_uniform_buf: wgpu::Buffer,
// plane_vertex_buf: wgpu::Buffer,
// plane_index_buf: wgpu::Buffer,
} }
impl Renderer { impl Renderer {
@ -94,20 +93,33 @@ impl Renderer {
} }
} }
//#[system(for_each)] /*
SOOOOOOOOOOOOooo... Legion systems have to be standalone functions, which is fine
we can do a special kind of song and dance
Main loop {
renderer
runtime
render_system(param1,2,3, renderer);
animation_system(param1,2,3, runtime);
renderer.finalize()
}
*/
#[system] #[system]
#[write_component(Position)] #[write_component(Position)]
#[write_component(Mesh)] #[write_component(Mesh)]
#[write_component(Color)] #[write_component(Color)]
pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) { pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
let frame = renderer.get_current_frame(); let frame = renderer.get_current_frame();
let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query(); let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query();
// update uniforms // Update the entity uniforms
for (pos, mesh, color) in query.iter_mut(world) { for (pos, mesh, color) in query.iter_mut(world) {
// Revolve the entity by the rotation speed, only if it is non-zero // Revolve the entity by the rotation speed, only if it is non-zero
// if vel.rs != 0.0 { // if vel.rs != 0.0 {
// let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(vel.rs)); // let rotation = cgmath::Matrix4::from_angle_x(cgmath::Deg(vel.rs));
@ -123,7 +135,9 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
color.a as f32, color.a as f32,
], ],
}; };
renderer.queue.write_buffer(&mesh.uniform_buf, 0, bytemuck::bytes_of(&data)); renderer
.queue
.write_buffer(&mesh.uniform_buffer, 0, bytemuck::bytes_of(&data));
} }
// if self.lights_are_dirty { // if self.lights_are_dirty {
@ -196,7 +210,12 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
attachment: &frame.output.view, attachment: &frame.output.view,
resolve_target: None, resolve_target: None,
ops: wgpu::Operations { ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }), load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true, store: true,
}, },
}], }],
@ -212,17 +231,30 @@ pub fn render_test(world: &mut SubWorld, #[resource] renderer: &mut Renderer) {
pass.set_pipeline(&renderer.forward_pass.pipeline); pass.set_pipeline(&renderer.forward_pass.pipeline);
pass.set_bind_group(0, &renderer.forward_pass.bind_group, &[]); pass.set_bind_group(0, &renderer.forward_pass.bind_group, &[]);
// for entity in &self.entities { let mut query = <(&mut Position, &mut Mesh, &mut Color)>::query();
// pass.set_bind_group(1, &entity.bind_group, &[]);
// pass.set_index_buffer(entity.index_buf.slice(..)); for (pos, mesh, color) in query.iter_mut(world) {
// pass.set_vertex_buffer(0, entity.vertex_buf.slice(..)); pass.set_bind_group(1, &mesh.bind_group, &[]);
// pass.draw_indexed(0..entity.index_count as u32, 0, 0..1); pass.set_index_buffer(mesh.index_buffer.slice(..));
// } pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
let data = EntityUniforms {
model: pos.mx.into(),
color: [
color.r as f32,
color.g as f32,
color.b as f32,
color.a as f32,
],
};
renderer
.queue
.write_buffer(&mesh.uniform_buffer, 0, bytemuck::bytes_of(&data));
}
} }
encoder.pop_debug_group(); encoder.pop_debug_group();
renderer.queue.submit(iter::once(encoder.finish())); renderer.queue.submit(iter::once(encoder.finish()));
} }
impl Renderer { impl Renderer {
@ -232,7 +264,9 @@ impl Renderer {
match self.swapchain.get_current_frame() { match self.swapchain.get_current_frame() {
Ok(frame) => frame, Ok(frame) => frame,
Err(_) => { Err(_) => {
self.swapchain = self.device.create_swap_chain(&self.surface, &self.swapchain_description); self.swapchain = self
.device
.create_swap_chain(&self.surface, &self.swapchain_description);
self.swapchain self.swapchain
.get_current_frame() .get_current_frame()
.expect("Failed to acquire next swap chain texture!") .expect("Failed to acquire next swap chain texture!")
@ -284,8 +318,9 @@ impl Renderer {
(vertex_buf, index_buf) (vertex_buf, index_buf)
} }
pub fn load_mesh_to_buffer(&self, filepath: &str) -> (Arc<Buffer>, Arc<Buffer>, Arc<Buffer>) { pub fn load_mesh_to_buffer(&self, filepath: &str) -> Mesh {
let (vertices, indices) = import_mesh(filepath); let (vertices, indices) = import_mesh(filepath);
let index_count = indices.len();
let (vertex_buf, index_buf) = Renderer::create_buffer(&self.device, indices, vertices); let (vertex_buf, index_buf) = Renderer::create_buffer(&self.device, indices, vertices);
let uniform_buf = Arc::new(self.device.create_buffer(&wgpu::BufferDescriptor { let uniform_buf = Arc::new(self.device.create_buffer(&wgpu::BufferDescriptor {
@ -294,7 +329,23 @@ impl Renderer {
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
mapped_at_creation: false, mapped_at_creation: false,
})); }));
(vertex_buf, index_buf, uniform_buf)
let bind_group = Arc::new(self.device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &self.entity_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(uniform_buf.slice(..)),
}],
label: None,
}));
Mesh {
index_buffer: index_buf,
index_count: index_count,
vertex_buffer: vertex_buf,
uniform_buffer: uniform_buf,
bind_group: bind_group,
}
} }
pub fn init(window: Window) -> Renderer { pub fn init(window: Window) -> Renderer {
@ -345,8 +396,6 @@ impl Renderer {
let queue = Arc::new(queue); let queue = Arc::new(queue);
let device = Arc::new(device); let device = Arc::new(device);
// This is some gross-ass web shit // This is some gross-ass web shit
/*#[cfg(target_arch = "wasm32")] /*#[cfg(target_arch = "wasm32")]
let spawner = { let spawner = {
@ -429,7 +478,7 @@ impl Renderer {
}; };
// This is also in the runtime which really shouldn't have this // This is also in the runtime which really shouldn't have this
let local_bind_group_layout = let entity_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None, label: None,
entries: &[wgpu::BindGroupLayoutEntry { entries: &[wgpu::BindGroupLayoutEntry {
@ -445,6 +494,7 @@ impl Renderer {
}], }],
}); });
/* /*
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
@ -471,7 +521,7 @@ impl Renderer {
// Pipeline is similar between passes, but with a different label // 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, &entity_bind_group_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -591,7 +641,7 @@ impl Renderer {
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, &entity_bind_group_layout],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -745,18 +795,15 @@ impl Renderer {
shadow_pass, shadow_pass,
forward_pass, forward_pass,
forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()), forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()),
entity_bind_group_layout: entity_bind_group_layout,
light_uniform_buf, light_uniform_buf,
// plane_uniform_buf,
// plane_vertex_buf: (),
// plane_index_buf: ()
swapchain_description: sc_desc, swapchain_description: sc_desc,
surface, surface,
instance: Arc::new(instance) instance: Arc::new(instance),
} }
} }
pub fn render( pub fn render(
&mut self, &mut self,
frame: &wgpu::SwapChainTexture, frame: &wgpu::SwapChainTexture,
@ -885,7 +932,6 @@ impl Renderer {
encoder.pop_debug_group(); encoder.pop_debug_group();
queue.submit(iter::once(encoder.finish())); queue.submit(iter::once(encoder.finish()));
} }
pub(crate) fn required_features() -> wgpu::Features { pub(crate) fn required_features() -> wgpu::Features {

Loading…
Cancel
Save