Add RenderState

This commit is contained in:
mars 2022-05-15 13:40:25 -06:00
parent a622696fe9
commit 73eceb601e
3 changed files with 231 additions and 1 deletions

View File

@ -4,10 +4,12 @@ version = "0.1.0"
edition = "2021"
[dependencies]
cyborg = { path = "../" }
cyborg = { path = "../", features = ["legion"] }
egui = "0.17.0"
egui-winit = "0.17.0"
egui_wgpu_backend = "0.17.0"
glam = "0.20"
legion = "^0.4"
pollster = "0.2"
puffin = "^0.13"
puffin_egui = "0.14.0"

View File

@ -9,6 +9,7 @@ use egui_winit::winit::{
};
use std::sync::Arc;
mod render;
mod ui;
struct Application {
@ -22,6 +23,7 @@ struct Application {
egui_ctx: egui::Context,
egui_rp: EguiRenderPass,
ui: ui::UserInterface,
render_state: render::RenderState,
}
impl Application {
@ -64,6 +66,8 @@ impl Application {
let egui_ctx = egui::Context::default();
let egui_rp = egui_wgpu_backend::RenderPass::new(&device, config.format, 1);
let render_state = render::RenderState::new(device.clone(), queue.clone(), config.format);
Self {
window,
device,
@ -75,6 +79,7 @@ impl Application {
egui_ctx,
egui_rp,
ui: ui::UserInterface::new(),
render_state,
}
}
@ -104,6 +109,11 @@ impl Application {
self.egui_ctx.run(raw_input, |ctx| self.ui.run(ctx))
};
{
puffin::profile_scope!("Main render");
self.render_state.render();
}
puffin::profile_scope!("Render egui");
self.egui_state.handle_platform_output(

218
editor/src/render.rs Normal file
View File

@ -0,0 +1,218 @@
use crate::wgpu;
use cyborg::camera::Camera;
use cyborg::viewport::{Viewport, ViewportInfo, ViewportViews};
use std::sync::Arc;
pub struct OffscreenTextures {
width: u32,
height: u32,
output_texture: wgpu::Texture,
output_view: wgpu::TextureView,
depth_texture: wgpu::Texture,
depth_view: wgpu::TextureView,
}
impl OffscreenTextures {
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
pub fn new(
device: &wgpu::Device,
width: u32,
height: u32,
output_format: wgpu::TextureFormat,
) -> Self {
let size = wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
};
let mut tex_desc = wgpu::TextureDescriptor {
label: None,
size,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: output_format,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
};
tex_desc.label = Some("Offscreen Output Texture");
let output_texture = device.create_texture(&tex_desc);
tex_desc.label = Some("Offscreen Depth Texture");
tex_desc.format = Self::DEPTH_FORMAT;
let depth_texture = device.create_texture(&tex_desc);
let view_desc = wgpu::TextureViewDescriptor::default();
let output_view = output_texture.create_view(&view_desc);
let depth_view = depth_texture.create_view(&view_desc);
Self {
width,
height,
output_texture,
output_view,
depth_texture,
depth_view,
}
}
}
pub struct OffscreenViewport {
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
output_format: wgpu::TextureFormat,
textures: OffscreenTextures,
}
impl OffscreenViewport {
pub fn new(
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
output_format: wgpu::TextureFormat,
) -> Self {
let textures = OffscreenTextures::new(&device, 640, 480, output_format);
Self {
device,
queue,
output_format,
textures,
}
}
pub fn get_camera(&self) -> Camera {
Camera {
eye: [1.0, 1.0, 1.0, 0.0],
vp: Default::default(),
}
}
}
impl Viewport for OffscreenViewport {
fn get_info(&self) -> ViewportInfo {
ViewportInfo {
output_format: self.output_format,
depth_format: OffscreenTextures::DEPTH_FORMAT,
}
}
fn get_queue(&self) -> &wgpu::Queue {
&self.queue
}
fn get_views(&self) -> ViewportViews {
ViewportViews {
output: &self.textures.output_view,
depth: &self.textures.depth_view,
}
}
}
pub struct ViewportStore {
device: Arc<wgpu::Device>,
output_format: wgpu::TextureFormat,
viewport: OffscreenViewport,
}
impl ViewportStore {
pub fn new(
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
output_format: wgpu::TextureFormat,
) -> Self {
Self {
device: device.clone(),
output_format,
viewport: OffscreenViewport::new(device, queue, output_format),
}
}
}
impl cyborg::legion::RenderCallbacks for ViewportStore {
fn get_viewports(&mut self) -> Vec<(&dyn Viewport, Camera)> {
vec![(&self.viewport, self.viewport.get_camera())]
}
fn present(&mut self) {}
}
pub struct RenderState {
pub world: legion::World,
pub resources: legion::Resources,
pub render_schedule: legion::Schedule,
}
impl RenderState {
pub fn new(
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
output_format: wgpu::TextureFormat,
) -> Self {
use cyborg::shader::{ShaderStore, ShaderWatcher};
let mut world = legion::World::default();
let mut resources = legion::Resources::default();
let viewport_store = ViewportStore::new(device.clone(), queue.clone(), output_format);
let renderer = cyborg::Renderer::new(device.clone(), queue.clone());
resources.insert(renderer);
let viewport_info = ViewportInfo {
output_format,
depth_format: OffscreenTextures::DEPTH_FORMAT,
};
resources.insert(viewport_info);
let shader_store = Arc::new(ShaderStore::new(device.clone()));
let shaders_dir = std::env::current_dir().unwrap();
let shaders_dir = shaders_dir.join("shaders/");
let shader_watcher = ShaderWatcher::new(shader_store.to_owned(), shaders_dir).unwrap();
let mesh_forward = shader_watcher.add_file("mesh_forward.wgsl").unwrap();
let mesh_skinning = shader_watcher.add_file("mesh_skinning.wgsl").unwrap();
let mesh_shaders = cyborg::pass::mesh::ShaderInfo {
store: shader_store.clone(),
forward: mesh_forward,
skinning: mesh_skinning,
};
resources.insert(mesh_shaders);
let mut render_schedule = legion::Schedule::builder();
cyborg::legion::build_renderer(viewport_store, &mut resources, &mut render_schedule);
let render_schedule = render_schedule.build();
world.push((
cyborg::scene::Transform {
transform: Default::default(),
},
cyborg::scene::DebugDrawList {
vertices: vec![
cyborg::scene::DebugVertex {
color: [1.0, 0.0, 0.0],
position: [0.0, 0.0, -1.0],
},
cyborg::scene::DebugVertex {
color: [0.0, 0.0, 1.0],
position: [0.0, 0.0, 1.0],
},
],
indices: vec![0, 1],
},
));
Self {
world,
resources,
render_schedule,
}
}
pub fn render(&mut self) {
self.render_schedule
.execute(&mut self.world, &mut self.resources);
}
}