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(
@ -81,15 +79,15 @@ pub enum ShaderStage {
} }
/* /*
window: winit::window::Window, window: winit::window::Window,
event_loop: EventLoop<()>, event_loop: EventLoop<()>,
instance: wgpu::Instance, instance: wgpu::Instance,
size: winit::dpi::PhysicalSize<u32>, size: winit::dpi::PhysicalSize<u32>,
surface: wgpu::Surface, surface: wgpu::Surface,
adapter: wgpu::Adapter, adapter: wgpu::Adapter,
device: wgpu::Device, device: wgpu::Device,
queue: wgpu::Queue, queue: wgpu::Queue,
*/ */
// a component is any type that is 'static, sized, send and sync // a component is any type that is 'static, sized, send and sync
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@ -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");
@ -169,7 +168,7 @@ fn main() {
*/ */
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
let (mut pool, spawner) = { let (mut pool, spawner) = {
let local_pool = futures::executor::LocalPool::new(); let local_pool = futures::executor::LocalPool::new();
let spawner = local_pool.spawner(); let spawner = local_pool.spawner();
(local_pool, spawner) (local_pool, spawner)
@ -196,26 +195,26 @@ fn main() {
// I don't know what they are doing here // I don't know what they are doing here
#[cfg(windows_OFF)] // TODO #[cfg(windows_OFF)] // TODO
{ {
use winit::platform::windows::WindowBuilderExtWindows; use winit::platform::windows::WindowBuilderExtWindows;
builder = builder.with_no_redirection_bitmap(true); builder = builder.with_no_redirection_bitmap(true);
} }
// I think right here is where I can start pulling everything into the renderer // I think right here is where I can start pulling everything into the renderer
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();
log::info!("Entering render loop..."); log::info!("Entering render loop...");
// 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...
@ -278,33 +312,37 @@ fn main() {
ControlFlow::Exit ControlFlow::Exit
} else { } else {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
// Artificially slows the loop rate to 10 millis // Artificially slows the loop rate to 10 millis
// This is called after redraw events cleared // This is called after redraw events cleared
ControlFlow::WaitUntil(Instant::now() + Duration::from_millis(10)) ControlFlow::WaitUntil(Instant::now() + Duration::from_millis(10))
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
ControlFlow::Poll ControlFlow::Poll
} }
}; };
match event { match event {
event::Event::MainEventsCleared => { event::Event::MainEventsCleared => {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
// 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
last_update_inst = Instant::now(); .get_mut::<Renderer>()
} .unwrap()
.window
pool.run_until_stalled(); .request_redraw();
last_update_inst = Instant::now();
} }
pool.run_until_stalled();
}
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
window.request_redraw(); window.request_redraw();
} }
// Resizing will queue a request_redraw // Resizing will queue a request_redraw
@ -316,18 +354,21 @@ 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);
} }
event::Event::WindowEvent { event, .. } => match event { event::Event::WindowEvent { event, .. } => match event {
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: input:
event::KeyboardInput { event::KeyboardInput {
virtual_keycode: Some(event::VirtualKeyCode::Escape), virtual_keycode: Some(event::VirtualKeyCode::Escape),
state: event::ElementState::Pressed, state: event::ElementState::Pressed,
.. ..
}, },
.. ..
} }
| WindowEvent::CloseRequested => { | WindowEvent::CloseRequested => {
@ -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