scene module + better trait/generic relationships
This commit is contained in:
parent
31e336f4ef
commit
7e855f5a46
|
@ -3,9 +3,9 @@ use std::f32::consts::LN_2;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use winit::event::{ElementState, VirtualKeyCode};
|
use winit::event::{ElementState, VirtualKeyCode};
|
||||||
|
|
||||||
pub trait Camera {
|
pub struct Camera {
|
||||||
fn get_eye(&self) -> [f32; 4];
|
pub eye: [f32; 4],
|
||||||
fn get_vp(&self) -> [[f32; 4]; 4];
|
pub vp: [[f32; 4]; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -209,14 +209,19 @@ impl Flycam {
|
||||||
fn get_orientation(&self) -> glam::Quat {
|
fn get_orientation(&self) -> glam::Quat {
|
||||||
Quat::from_euler(glam::EulerRot::YXZ, self.euler_y, self.euler_x, 0.0)
|
Quat::from_euler(glam::EulerRot::YXZ, self.euler_y, self.euler_x, 0.0)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Camera for Flycam {
|
pub fn get_camera(&self) -> Camera {
|
||||||
fn get_eye(&self) -> [f32; 4] {
|
Camera {
|
||||||
|
eye: self.get_eye(),
|
||||||
|
vp: self.get_vp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_eye(&self) -> [f32; 4] {
|
||||||
self.position.extend(0.0).to_array()
|
self.position.extend(0.0).to_array()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_vp(&self) -> [[f32; 4]; 4] {
|
pub fn get_vp(&self) -> [[f32; 4]; 4] {
|
||||||
// view matrix is inverted camera pose (world space to camera space)
|
// view matrix is inverted camera pose (world space to camera space)
|
||||||
let rotation = Mat4::from_quat(self.get_orientation().inverse());
|
let rotation = Mat4::from_quat(self.get_orientation().inverse());
|
||||||
let translation = Mat4::from_translation(-self.position);
|
let translation = Mat4::from_translation(-self.position);
|
||||||
|
|
44
src/lib.rs
44
src/lib.rs
|
@ -1,13 +1,14 @@
|
||||||
//! Cyborg is a high-performance, modern, experimental rendering engine written
|
//! Cyborg is a high-performance, modern, experimental rendering engine written
|
||||||
//! in Rust.
|
//! in Rust.
|
||||||
|
|
||||||
|
use parking_lot::Mutex;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
pub mod pass;
|
pub mod pass;
|
||||||
pub mod phase;
|
pub mod phase;
|
||||||
|
pub mod scene;
|
||||||
pub mod shader;
|
pub mod shader;
|
||||||
pub mod staging;
|
pub mod staging;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
@ -16,7 +17,7 @@ pub mod viewport;
|
||||||
use camera::Camera;
|
use camera::Camera;
|
||||||
use pass::*;
|
use pass::*;
|
||||||
use phase::*;
|
use phase::*;
|
||||||
use viewport::ViewportImage;
|
use viewport::Viewport;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
@ -26,10 +27,10 @@ pub struct ViewportUniform {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewportUniform {
|
impl ViewportUniform {
|
||||||
pub fn from_camera(camera: &impl Camera) -> Self {
|
pub fn from_camera(camera: &Camera) -> Self {
|
||||||
Self {
|
Self {
|
||||||
eye: camera.get_eye(),
|
eye: camera.eye,
|
||||||
vp: camera.get_vp(),
|
vp: camera.vp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,21 +161,16 @@ impl Renderer {
|
||||||
&self.layouts
|
&self.layouts
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_pass<T: 'static + RenderPass>(&mut self, pass: T) {
|
pub fn get_frames_in_flight(&self) -> usize {
|
||||||
let pass = Arc::new(pass);
|
self.frames_in_flight
|
||||||
self.add_pass_arc(pass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_pass_arc<T: 'static + RenderPass>(&mut self, pass: Arc<T>) {
|
pub fn render<'a>(
|
||||||
let pass = RenderPassBox::new(pass, self.frames_in_flight);
|
&mut self,
|
||||||
self.add_pass_box(pass);
|
passes: &mut [&mut dyn RenderPassBoxTrait],
|
||||||
}
|
target: &dyn Viewport,
|
||||||
|
camera: &Camera,
|
||||||
pub fn add_pass_box(&mut self, pass: Box<dyn RenderPassBoxTrait>) {
|
) {
|
||||||
self.render_passes.push(pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render<'a>(&mut self, target: &impl ViewportImage<'a>, camera: &impl Camera) {
|
|
||||||
self.frame_index += 1;
|
self.frame_index += 1;
|
||||||
if self.frame_index >= self.frame_datas.len() {
|
if self.frame_index >= self.frame_datas.len() {
|
||||||
self.frame_index = 0;
|
self.frame_index = 0;
|
||||||
|
@ -193,7 +189,7 @@ impl Renderer {
|
||||||
let phase_passes = multimap::MultiMap::<Phase, usize>::new();
|
let phase_passes = multimap::MultiMap::<Phase, usize>::new();
|
||||||
let phase_passes = std::sync::Mutex::new(phase_passes);
|
let phase_passes = std::sync::Mutex::new(phase_passes);
|
||||||
|
|
||||||
self.render_passes
|
passes
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(pass_index, rp)| {
|
.for_each(|(pass_index, rp)| {
|
||||||
|
@ -219,7 +215,7 @@ impl Renderer {
|
||||||
if let Some(upload) = phase_passes.get_vec(&Phase::Upload) {
|
if let Some(upload) = phase_passes.get_vec(&Phase::Upload) {
|
||||||
upload.iter().for_each(|pass_index| {
|
upload.iter().for_each(|pass_index| {
|
||||||
let phase_data = frame_data.make_phase_data(Phase::Upload, &viewport);
|
let phase_data = frame_data.make_phase_data(Phase::Upload, &viewport);
|
||||||
let pass = &self.render_passes[*pass_index];
|
let pass = &passes[*pass_index];
|
||||||
pass.record_commands(phase_data, &mut encoder);
|
pass.record_commands(phase_data, &mut encoder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -231,17 +227,17 @@ impl Renderer {
|
||||||
|
|
||||||
skinning.iter().for_each(|pass_index| {
|
skinning.iter().for_each(|pass_index| {
|
||||||
let phase_data = frame_data.make_phase_data(Phase::Skinning, &viewport);
|
let phase_data = frame_data.make_phase_data(Phase::Skinning, &viewport);
|
||||||
let pass = &self.render_passes[*pass_index];
|
let pass = &passes[*pass_index];
|
||||||
pass.record_compute(phase_data, &mut cmds);
|
pass.record_compute(phase_data, &mut cmds);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let record_render = |phase| {
|
let record_render = |phase| {
|
||||||
let cmds = Mutex::new(Vec::new());
|
let cmds = Mutex::new(Vec::new());
|
||||||
if let Some(passes) = phase_passes.get_vec(&phase) {
|
if let Some(phase_passes) = phase_passes.get_vec(&phase) {
|
||||||
passes.par_iter().for_each(|pass_index| {
|
phase_passes.par_iter().for_each(|pass_index| {
|
||||||
let phase_data = frame_data.make_phase_data(phase, &viewport);
|
let phase_data = frame_data.make_phase_data(phase, &viewport);
|
||||||
let pass = &self.render_passes[*pass_index];
|
let pass = &passes[*pass_index];
|
||||||
|
|
||||||
if let Some(cmd) = pass.record_render(phase_data) {
|
if let Some(cmd) = pass.record_render(phase_data) {
|
||||||
cmds.lock().push(cmd);
|
cmds.lock().push(cmd);
|
||||||
|
|
75
src/main.rs
75
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
use cyborg::shader;
|
use cyborg::shader;
|
||||||
|
use cyborg::storage::mesh::*;
|
||||||
use cyborg::{pass, viewport::*, Renderer};
|
use cyborg::{pass, viewport::*, Renderer};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use winit::{
|
use winit::{
|
||||||
|
@ -13,7 +14,7 @@ fn main() {
|
||||||
let mut viewport = pollster::block_on(WinitViewport::from_window(&window));
|
let mut viewport = pollster::block_on(WinitViewport::from_window(&window));
|
||||||
let mut renderer = Renderer::new(viewport.device.clone(), viewport.queue.clone());
|
let mut renderer = Renderer::new(viewport.device.clone(), viewport.queue.clone());
|
||||||
|
|
||||||
let mut camera = cyborg::camera::Flycam::new(0.002, 10.0, 0.25);
|
let mut flycam = cyborg::camera::Flycam::new(0.002, 10.0, 0.25);
|
||||||
let mut is_grabbed = false;
|
let mut is_grabbed = false;
|
||||||
|
|
||||||
let device = renderer.get_device();
|
let device = renderer.get_device();
|
||||||
|
@ -43,31 +44,85 @@ fn main() {
|
||||||
let debug_pass =
|
let debug_pass =
|
||||||
pass::debug::DebugPass::new(device.to_owned(), layouts.to_owned(), viewport.get_info());
|
pass::debug::DebugPass::new(device.to_owned(), layouts.to_owned(), viewport.get_info());
|
||||||
|
|
||||||
renderer.add_pass(mesh_pass);
|
let example_vertices = vec![
|
||||||
renderer.add_pass(debug_pass);
|
pass::mesh::Vertex {
|
||||||
|
position: [-0.5, 0.5, 0.0],
|
||||||
|
tan_frame: 0,
|
||||||
|
},
|
||||||
|
pass::mesh::Vertex {
|
||||||
|
position: [0.5, 0.5, 0.0],
|
||||||
|
tan_frame: 0,
|
||||||
|
},
|
||||||
|
pass::mesh::Vertex {
|
||||||
|
position: [0.0, -0.5, 0.0],
|
||||||
|
tan_frame: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let example_vertices = AttrBuffer {
|
||||||
|
id: mesh_pass.get_vertex_attr_id(),
|
||||||
|
count: example_vertices.len(),
|
||||||
|
data: bytemuck::cast_slice(&example_vertices).to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let example_indices = vec![0u32, 1u32, 2u32];
|
||||||
|
let example_indices = AttrBuffer {
|
||||||
|
id: mesh_pass.get_index_attr_id(),
|
||||||
|
count: example_indices.len(),
|
||||||
|
data: bytemuck::cast_slice(&example_indices).to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut example_mesh = MeshBuffer::default();
|
||||||
|
example_mesh.attributes.push(example_vertices);
|
||||||
|
example_mesh.attributes.push(example_indices);
|
||||||
|
let example_mesh = mesh_pass.get_mesh_pool().load(example_mesh).unwrap();
|
||||||
|
|
||||||
|
let meshes = mesh_pass.get_meshes().to_owned();
|
||||||
|
|
||||||
|
let r = 8;
|
||||||
|
let mut meshes_lock = meshes.write();
|
||||||
|
for x in -r..r {
|
||||||
|
for y in -r..r {
|
||||||
|
for z in -r..r {
|
||||||
|
let translation = glam::Vec3::new(x as f32, y as f32, z as f32);
|
||||||
|
let transform = glam::Mat4::from_translation(translation);
|
||||||
|
meshes_lock.transformed.push(cyborg::scene::TransformedMesh {
|
||||||
|
transform,
|
||||||
|
mesh: example_mesh.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drop(meshes_lock);
|
||||||
|
|
||||||
|
let frames_in_flight = renderer.get_frames_in_flight();
|
||||||
|
let mut mesh_pass = pass::RenderPassBox::new(Arc::new(mesh_pass), frames_in_flight);
|
||||||
|
let mut debug_pass = pass::RenderPassBox::new(Arc::new(debug_pass), frames_in_flight);
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| match event {
|
event_loop.run(move |event, _, control_flow| match event {
|
||||||
Event::RedrawRequested(_) => {
|
Event::RedrawRequested(_) => {
|
||||||
println!("camera: {:#?}", camera);
|
|
||||||
match viewport.acquire() {
|
match viewport.acquire() {
|
||||||
Err(wgpu::SurfaceError::Lost) => viewport.resize(viewport.size),
|
Err(wgpu::SurfaceError::Lost) => viewport.resize(viewport.size),
|
||||||
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
|
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
|
||||||
Err(e) => eprintln!("error: {:?}", e),
|
Err(e) => eprintln!("error: {:?}", e),
|
||||||
Ok(target) => {
|
Ok(_) => {
|
||||||
renderer.render(&target, &camera);
|
let mut passes: Vec<&mut dyn pass::RenderPassBoxTrait> = Vec::new();
|
||||||
target.present();
|
passes.push(&mut mesh_pass);
|
||||||
|
passes.push(&mut debug_pass);
|
||||||
|
renderer.render(passes.as_mut_slice(), &viewport, &flycam.get_camera());
|
||||||
|
viewport.present();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::MainEventsCleared => {
|
Event::MainEventsCleared => {
|
||||||
shader_watcher.watch();
|
shader_watcher.watch();
|
||||||
camera.update();
|
flycam.update();
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
}
|
}
|
||||||
Event::DeviceEvent { ref event, .. } => match event {
|
Event::DeviceEvent { ref event, .. } => match event {
|
||||||
DeviceEvent::MouseMotion { delta } => {
|
DeviceEvent::MouseMotion { delta } => {
|
||||||
if is_grabbed {
|
if is_grabbed {
|
||||||
camera.process_mouse(delta.0, delta.1);
|
flycam.process_mouse(delta.0, delta.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -92,7 +147,7 @@ fn main() {
|
||||||
is_grabbed = false;
|
is_grabbed = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
camera.process_keyboard(*key, *state);
|
flycam.process_keyboard(*key, *state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowEvent::MouseInput {
|
WindowEvent::MouseInput {
|
||||||
|
|
12
src/pass.rs
12
src/pass.rs
|
@ -97,17 +97,23 @@ impl<T: 'static + RenderPass> RenderPassBox<T> {
|
||||||
///
|
///
|
||||||
/// Calls to [RenderPassBoxTrait] functions with frame indices greater
|
/// Calls to [RenderPassBoxTrait] functions with frame indices greater
|
||||||
/// than or equal to `frame_num` are out-of-bounds and will panic.
|
/// than or equal to `frame_num` are out-of-bounds and will panic.
|
||||||
pub fn new(render_pass: Arc<T>, frame_num: usize) -> Box<dyn RenderPassBoxTrait> {
|
pub fn new(render_pass: Arc<T>, frame_num: usize) -> Self {
|
||||||
let frame_data = {
|
let frame_data = {
|
||||||
(0..frame_num)
|
(0..frame_num)
|
||||||
.map(|_| render_pass.create_frame_data())
|
.map(|_| render_pass.create_frame_data())
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
Box::new(Self {
|
Self {
|
||||||
render_pass,
|
render_pass,
|
||||||
frame_data,
|
frame_data,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as [Self::new], but creates a boxed [RenderPassBoxTrait] in a
|
||||||
|
/// generic-friendly interface.
|
||||||
|
pub fn new_boxed(render_pass: Arc<T>, frame_num: usize) -> Box<dyn RenderPassBoxTrait> {
|
||||||
|
Box::new(Self::new(render_pass, frame_num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,28 +2,7 @@ use super::*;
|
||||||
use crate::storage::GpuVec;
|
use crate::storage::GpuVec;
|
||||||
use crate::viewport::ViewportInfo;
|
use crate::viewport::ViewportInfo;
|
||||||
use crate::RenderLayouts;
|
use crate::RenderLayouts;
|
||||||
|
use crate::scene::{DebugVertex as Vertex, DebugIndex as Index};
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
|
||||||
pub struct Vertex {
|
|
||||||
pub position: [f32; 3],
|
|
||||||
pub color: [f32; 3],
|
|
||||||
}
|
|
||||||
|
|
||||||
const VERTEX_ATTRS: &[wgpu::VertexAttribute] =
|
|
||||||
&wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3];
|
|
||||||
|
|
||||||
impl Vertex {
|
|
||||||
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
|
|
||||||
wgpu::VertexBufferLayout {
|
|
||||||
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
|
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
|
||||||
attributes: VERTEX_ATTRS,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Index = u32;
|
|
||||||
|
|
||||||
pub struct FrameData {
|
pub struct FrameData {
|
||||||
vertices: GpuVec<Vertex>,
|
vertices: GpuVec<Vertex>,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::scene;
|
||||||
use crate::shader::{ShaderHandle, ShaderStore};
|
use crate::shader::{ShaderHandle, ShaderStore};
|
||||||
use crate::storage::mesh::*;
|
use crate::storage::mesh::*;
|
||||||
use crate::storage::GpuVec;
|
use crate::storage::GpuVec;
|
||||||
use crate::viewport::ViewportInfo;
|
use crate::viewport::ViewportInfo;
|
||||||
use crate::RenderLayouts;
|
use crate::RenderLayouts;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ShaderInfo {
|
pub struct ShaderInfo {
|
||||||
pub store: Arc<ShaderStore>,
|
pub store: Arc<ShaderStore>,
|
||||||
pub forward: ShaderHandle,
|
pub forward: ShaderHandle,
|
||||||
|
@ -66,11 +68,6 @@ struct MeshGroupCommands {
|
||||||
meshes: Vec<MeshCommand>,
|
meshes: Vec<MeshCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MeshInstance {
|
|
||||||
pub transform: glam::Mat4,
|
|
||||||
pub mesh: MeshHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FrameData {
|
pub struct FrameData {
|
||||||
skinned_vertices: GpuVec<Vertex>,
|
skinned_vertices: GpuVec<Vertex>,
|
||||||
skinning_uniforms: GpuVec<SkinningUniform>,
|
skinning_uniforms: GpuVec<SkinningUniform>,
|
||||||
|
@ -86,13 +83,12 @@ pub struct MeshPass {
|
||||||
vertex_attr_id: AttrId,
|
vertex_attr_id: AttrId,
|
||||||
index_attr_id: AttrId,
|
index_attr_id: AttrId,
|
||||||
mesh_layout_id: MeshLayoutId,
|
mesh_layout_id: MeshLayoutId,
|
||||||
example_mesh: MeshHandle,
|
|
||||||
skinning_bind_group_layout: wgpu::BindGroupLayout,
|
skinning_bind_group_layout: wgpu::BindGroupLayout,
|
||||||
skinning_pipeline: wgpu::ComputePipeline,
|
skinning_pipeline: wgpu::ComputePipeline,
|
||||||
depth_pipeline: wgpu::RenderPipeline,
|
depth_pipeline: wgpu::RenderPipeline,
|
||||||
opaque_pipeline: wgpu::RenderPipeline,
|
opaque_pipeline: wgpu::RenderPipeline,
|
||||||
target_info: ViewportInfo,
|
target_info: ViewportInfo,
|
||||||
instances: Vec<MeshInstance>,
|
meshes: scene::MeshesHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshPass {
|
impl MeshPass {
|
||||||
|
@ -119,54 +115,6 @@ impl MeshPass {
|
||||||
mesh_layout.insert(index_attr_id, ());
|
mesh_layout.insert(index_attr_id, ());
|
||||||
let mesh_layout_id = mesh_pool.add_layout(mesh_layout).unwrap();
|
let mesh_layout_id = mesh_pool.add_layout(mesh_layout).unwrap();
|
||||||
|
|
||||||
let example_vertices = vec![
|
|
||||||
Vertex {
|
|
||||||
position: [-0.5, 0.5, 0.0],
|
|
||||||
tan_frame: 0,
|
|
||||||
},
|
|
||||||
Vertex {
|
|
||||||
position: [0.5, 0.5, 0.0],
|
|
||||||
tan_frame: 0,
|
|
||||||
},
|
|
||||||
Vertex {
|
|
||||||
position: [0.0, -0.5, 0.0],
|
|
||||||
tan_frame: 0,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
let example_vertices = AttrBuffer {
|
|
||||||
id: vertex_attr_id,
|
|
||||||
count: example_vertices.len(),
|
|
||||||
data: bytemuck::cast_slice(&example_vertices).to_vec(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let example_indices = vec![0u32, 1u32, 2u32];
|
|
||||||
let example_indices = AttrBuffer {
|
|
||||||
id: index_attr_id,
|
|
||||||
count: example_indices.len(),
|
|
||||||
data: bytemuck::cast_slice(&example_indices).to_vec(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut example_mesh = MeshBuffer::default();
|
|
||||||
example_mesh.attributes.push(example_vertices);
|
|
||||||
example_mesh.attributes.push(example_indices);
|
|
||||||
let example_mesh = mesh_pool.load(example_mesh).unwrap();
|
|
||||||
|
|
||||||
let mut instances = Vec::new();
|
|
||||||
let r = 4;
|
|
||||||
for x in -r..r {
|
|
||||||
for y in -r..r {
|
|
||||||
for z in -r..r {
|
|
||||||
let translation = glam::Vec3::new(x as f32, y as f32, z as f32);
|
|
||||||
let transform = glam::Mat4::from_translation(translation);
|
|
||||||
instances.push(MeshInstance {
|
|
||||||
transform,
|
|
||||||
mesh: example_mesh.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let render_pipeline_layout =
|
let render_pipeline_layout =
|
||||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some("MeshPass Pipeline Layout"),
|
label: Some("MeshPass Pipeline Layout"),
|
||||||
|
@ -297,15 +245,30 @@ impl MeshPass {
|
||||||
index_attr_id,
|
index_attr_id,
|
||||||
vertex_attr_id,
|
vertex_attr_id,
|
||||||
mesh_layout_id,
|
mesh_layout_id,
|
||||||
example_mesh,
|
|
||||||
skinning_bind_group_layout,
|
skinning_bind_group_layout,
|
||||||
skinning_pipeline,
|
skinning_pipeline,
|
||||||
depth_pipeline,
|
depth_pipeline,
|
||||||
opaque_pipeline,
|
opaque_pipeline,
|
||||||
target_info,
|
target_info,
|
||||||
instances,
|
meshes: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mesh_pool(&self) -> &MeshPool {
|
||||||
|
&self.mesh_pool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_vertex_attr_id(&self) -> AttrId {
|
||||||
|
self.vertex_attr_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_index_attr_id(&self) -> AttrId {
|
||||||
|
self.index_attr_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_meshes(&self) -> &scene::MeshesHandle {
|
||||||
|
&self.meshes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderPass for MeshPass {
|
impl RenderPass for MeshPass {
|
||||||
|
@ -343,9 +306,12 @@ impl RenderPass for MeshPass {
|
||||||
data.groups.clear();
|
data.groups.clear();
|
||||||
data.skinning_uniforms.clear();
|
data.skinning_uniforms.clear();
|
||||||
|
|
||||||
|
let meshes_read = self.meshes.read();
|
||||||
let mesh_bindings = self
|
let mesh_bindings = self
|
||||||
.mesh_pool
|
.mesh_pool
|
||||||
.iter_meshes(self.mesh_layout_id, self.instances.iter(), |i| &i.mesh)
|
.iter_meshes(self.mesh_layout_id, meshes_read.transformed.iter(), |i| {
|
||||||
|
&i.mesh
|
||||||
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut skinned_cursor = 0;
|
let mut skinned_cursor = 0;
|
||||||
|
@ -468,8 +434,6 @@ impl RenderPass for MeshPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record_render(&self, data: PhaseData<&FrameData>) -> Option<wgpu::RenderBundle> {
|
fn record_render(&self, data: PhaseData<&FrameData>) -> Option<wgpu::RenderBundle> {
|
||||||
println!("MeshPass::record_render(phase: {:?})", data.phase);
|
|
||||||
|
|
||||||
let pipeline = match data.phase {
|
let pipeline = match data.phase {
|
||||||
Phase::Depth => &self.depth_pipeline,
|
Phase::Depth => &self.depth_pipeline,
|
||||||
Phase::Opaque => &self.opaque_pipeline,
|
Phase::Opaque => &self.opaque_pipeline,
|
||||||
|
@ -491,7 +455,7 @@ impl RenderPass for MeshPass {
|
||||||
});
|
});
|
||||||
|
|
||||||
// yikes
|
// yikes
|
||||||
let mesh_bindings: Vec<(MeshLayoutBindings, &Vec<MeshCommand>)> = data
|
let mesh_bindings: Vec<_> = data
|
||||||
.frame_data
|
.frame_data
|
||||||
.groups
|
.groups
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
//! Traits for describing Cyborg's scene representation.
|
||||||
|
//!
|
||||||
|
//! TODO this will all need to be replaced in favor of a way to represent
|
||||||
|
//! querying component and resource data framework-agnostically
|
||||||
|
|
||||||
|
use crate::storage::mesh::MeshHandle;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct TransformedMesh {
|
||||||
|
pub transform: glam::Mat4,
|
||||||
|
pub mesh: MeshHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Meshes {
|
||||||
|
pub transformed: Vec<TransformedMesh>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MeshesHandle = Arc<RwLock<Meshes>>;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
|
pub struct DebugVertex {
|
||||||
|
pub position: [f32; 3],
|
||||||
|
pub color: [f32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DEBUG_VERTEX_ATTRS: &[wgpu::VertexAttribute] =
|
||||||
|
&wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3];
|
||||||
|
|
||||||
|
impl DebugVertex {
|
||||||
|
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
|
||||||
|
wgpu::VertexBufferLayout {
|
||||||
|
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
|
||||||
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
|
attributes: DEBUG_VERTEX_ATTRS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DebugIndex = u32;
|
||||||
|
|
||||||
|
pub struct DebugDraw {
|
||||||
|
pub vertices: Vec<DebugVertex>,
|
||||||
|
pub indices: Vec<DebugIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DebugDraws {
|
||||||
|
pub draws: Vec<DebugDraw>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DebugDrawsHandle = Arc<RwLock<DebugDraws>>;
|
|
@ -14,12 +14,6 @@ pub struct ViewportViews<'a> {
|
||||||
pub trait Viewport {
|
pub trait Viewport {
|
||||||
fn get_info(&self) -> ViewportInfo;
|
fn get_info(&self) -> ViewportInfo;
|
||||||
fn get_queue(&self) -> &wgpu::Queue;
|
fn get_queue(&self) -> &wgpu::Queue;
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ViewportImage<'a> {
|
|
||||||
type Viewport: Viewport;
|
|
||||||
|
|
||||||
fn get_viewport(&self) -> &Self::Viewport;
|
|
||||||
fn get_views(&self) -> ViewportViews;
|
fn get_views(&self) -> ViewportViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,11 +21,13 @@ pub struct WinitViewport {
|
||||||
pub device: Arc<wgpu::Device>,
|
pub device: Arc<wgpu::Device>,
|
||||||
pub queue: Arc<wgpu::Queue>,
|
pub queue: Arc<wgpu::Queue>,
|
||||||
pub size: winit::dpi::PhysicalSize<u32>,
|
pub size: winit::dpi::PhysicalSize<u32>,
|
||||||
pub surface: wgpu::Surface,
|
surface: wgpu::Surface,
|
||||||
pub config: wgpu::SurfaceConfiguration,
|
config: wgpu::SurfaceConfiguration,
|
||||||
pub info: ViewportInfo,
|
info: ViewportInfo,
|
||||||
pub depth_texture: wgpu::Texture,
|
depth_texture: wgpu::Texture,
|
||||||
pub depth_texture_view: wgpu::TextureView,
|
depth_texture_view: wgpu::TextureView,
|
||||||
|
surface_texture: Option<wgpu::SurfaceTexture>,
|
||||||
|
output_view: Option<wgpu::TextureView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitViewport {
|
impl WinitViewport {
|
||||||
|
@ -88,22 +84,18 @@ impl WinitViewport {
|
||||||
info,
|
info,
|
||||||
depth_texture,
|
depth_texture,
|
||||||
depth_texture_view,
|
depth_texture_view,
|
||||||
|
surface_texture: None,
|
||||||
|
output_view: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acquire(&mut self) -> Result<WinitImage, wgpu::SurfaceError> {
|
pub fn acquire(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||||
let surface_texture = self.surface.get_current_texture()?;
|
let surface_texture = self.surface.get_current_texture()?;
|
||||||
let output_view = surface_texture
|
self.output_view = Some(surface_texture
|
||||||
.texture
|
.texture
|
||||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
.create_view(&wgpu::TextureViewDescriptor::default()));
|
||||||
let depth_view = &self.depth_texture_view;
|
self.surface_texture = Some(surface_texture);
|
||||||
|
Ok(())
|
||||||
Ok(WinitImage {
|
|
||||||
viewport: self,
|
|
||||||
surface_texture,
|
|
||||||
output_view,
|
|
||||||
depth_view,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||||
|
@ -119,6 +111,12 @@ impl WinitViewport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn present(&mut self) {
|
||||||
|
if let Some(surface_texture) = self.surface_texture.take() {
|
||||||
|
surface_texture.present();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn make_depth_texture(
|
fn make_depth_texture(
|
||||||
device: &wgpu::Device,
|
device: &wgpu::Device,
|
||||||
config: &wgpu::SurfaceConfiguration,
|
config: &wgpu::SurfaceConfiguration,
|
||||||
|
@ -151,32 +149,12 @@ impl Viewport for WinitViewport {
|
||||||
fn get_queue(&self) -> &wgpu::Queue {
|
fn get_queue(&self) -> &wgpu::Queue {
|
||||||
&self.queue
|
&self.queue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WinitImage<'a> {
|
|
||||||
viewport: &'a WinitViewport,
|
|
||||||
surface_texture: wgpu::SurfaceTexture,
|
|
||||||
output_view: wgpu::TextureView,
|
|
||||||
depth_view: &'a wgpu::TextureView,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> WinitImage<'a> {
|
|
||||||
pub fn present(self) {
|
|
||||||
self.surface_texture.present();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ViewportImage<'a> for WinitImage<'a> {
|
|
||||||
type Viewport = WinitViewport;
|
|
||||||
|
|
||||||
fn get_viewport(&self) -> &WinitViewport {
|
|
||||||
self.viewport
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_views(&self) -> ViewportViews {
|
fn get_views(&self) -> ViewportViews {
|
||||||
ViewportViews {
|
let output = self.output_view.as_ref().unwrap();
|
||||||
output: &self.output_view,
|
ViewportViews {
|
||||||
depth: self.depth_view,
|
output,
|
||||||
|
depth: &self.depth_texture_view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue