Particles compiles and runs (no visuals yet)

This commit is contained in:
Imbris 2020-12-05 17:04:29 -05:00 committed by Avi Weinstock
parent b4df7e63e8
commit 0b9e1fdf6c
11 changed files with 98 additions and 147 deletions

View File

@ -40,7 +40,13 @@ pub use self::{
}, },
GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow,
}, },
renderer::{ColLightInfo, Drawer, Renderer, UiDrawer}, renderer::{
drawer::{
Drawer, FirstPassDrawer, ParticleDrawer, PreparedUiDrawer, SecondPassDrawer,
ThirdPassDrawer, UiDrawer,
},
ColLightInfo, Renderer,
},
texture::Texture, texture::Texture,
}; };
pub use wgpu::{AddressMode, FilterMode}; pub use wgpu::{AddressMode, FilterMode};

View File

@ -25,45 +25,6 @@ impl Locals {
} }
} }
/*#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
pub struct Vertex {
pos: [f32; 2],
}
impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] =
wgpu::vertex_attr_array![0 => Float2];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &ATTRIBUTES,
}
}
}
pub fn create_mesh() -> Mesh<Vertex> {
let mut mesh = Mesh::new();
#[rustfmt::skip]
mesh.push_tri(Tri::new(
Vertex { pos: [ 1.0, -1.0] },
Vertex { pos: [-1.0, 1.0] },
Vertex { pos: [-1.0, -1.0] },
));
#[rustfmt::skip]
mesh.push_tri(Tri::new(
Vertex { pos: [1.0, -1.0] },
Vertex { pos: [1.0, 1.0] },
Vertex { pos: [-1.0, 1.0] },
));
mesh
}*/
pub struct BindGroup { pub struct BindGroup {
pub(in super::super) bind_group: wgpu::BindGroup, pub(in super::super) bind_group: wgpu::BindGroup,
} }
@ -92,7 +53,10 @@ impl CloudsLayout {
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, ty: wgpu::BindingType::Sampler {
filtering: true,
comparison: false,
},
count: None, count: None,
}, },
// Depth source // Depth source
@ -109,7 +73,10 @@ impl CloudsLayout {
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 3, binding: 3,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, ty: wgpu::BindingType::Sampler {
filtering: true,
comparison: false,
},
count: None, count: None,
}, },
// Locals // Locals

View File

@ -349,7 +349,7 @@ impl GlobalsLayouts {
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture { ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: true }, sample_type: wgpu::TextureSampleType::Float { filterable: true },
view_dimension: wgpu::TextureViewDimension::D2, view_dimension: wgpu::TextureViewDimension::Cube,
multisampled: false, multisampled: false,
}, },
count: None, count: None,

View File

@ -174,7 +174,6 @@ impl ParticlePipeline {
device: &wgpu::Device, device: &wgpu::Device,
vs_module: &wgpu::ShaderModule, vs_module: &wgpu::ShaderModule,
fs_module: &wgpu::ShaderModule, fs_module: &wgpu::ShaderModule,
sc_desc: &wgpu::SwapChainDescriptor,
global_layout: &GlobalsLayouts, global_layout: &GlobalsLayouts,
aa_mode: AaMode, aa_mode: AaMode,
) -> Self { ) -> Self {
@ -216,7 +215,8 @@ impl ParticlePipeline {
}), }),
primitive_topology: wgpu::PrimitiveTopology::TriangleList, primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor { color_states: &[wgpu::ColorStateDescriptor {
format: sc_desc.format, // TODO pass this format in or make it a const
format: wgpu::TextureFormat::Rgba8UnormSrgb,
color_blend: wgpu::BlendDescriptor { color_blend: wgpu::BlendDescriptor {
src_factor: wgpu::BlendFactor::SrcAlpha, src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,

View File

@ -22,45 +22,6 @@ impl Locals {
} }
} }
/*#[repr(C)]
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
pub struct Vertex {
pub pos: [f32; 2],
}
impl Vertex {
fn desc<'a>() -> wgpu::VertexBufferDescriptor<'a> {
use std::mem;
const ATTRIBUTES: [wgpu::VertexAttributeDescriptor; 1] =
wgpu::vertex_attr_array![0 => Float2];
wgpu::VertexBufferDescriptor {
stride: mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: &ATTRIBUTES,
}
}
}
pub fn create_mesh() -> Mesh<Vertex> {
let mut mesh = Mesh::new();
#[rustfmt::skip]
mesh.push_tri(Tri::new(
Vertex { pos: [ 1.0, -1.0] },
Vertex { pos: [-1.0, 1.0] },
Vertex { pos: [-1.0, -1.0] },
));
#[rustfmt::skip]
mesh.push_tri(Tri::new(
Vertex { pos: [1.0, -1.0] },
Vertex { pos: [1.0, 1.0] },
Vertex { pos: [-1.0, 1.0] },
));
mesh
}*/
pub struct BindGroup { pub struct BindGroup {
pub(in super::super) bind_group: wgpu::BindGroup, pub(in super::super) bind_group: wgpu::BindGroup,
} }
@ -89,7 +50,10 @@ impl PostProcessLayout {
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 1, binding: 1,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler { filtering: true, comparison: false }, ty: wgpu::BindingType::Sampler {
filtering: true,
comparison: false,
},
count: None, count: None,
}, },
// Locals // Locals

View File

@ -1,7 +1,5 @@
mod binding; mod binding;
mod drawer; pub(super) mod drawer;
pub use drawer::{Drawer, UiDrawer};
use super::{ use super::{
consts::Consts, consts::Consts,
@ -172,12 +170,10 @@ impl Locals {
sampler, sampler,
&clouds_locals, &clouds_locals,
); );
let postprocess_bind = layouts.postprocess.bind( let postprocess_bind =
device, layouts
tgt_color_pp_view, .postprocess
sampler, .bind(device, tgt_color_pp_view, sampler, &postprocess_locals);
&postprocess_locals,
);
Self { Self {
clouds: clouds_locals, clouds: clouds_locals,
@ -203,12 +199,10 @@ impl Locals {
sampler, sampler,
&self.clouds, &self.clouds,
); );
self.postprocess_bind = layouts.postprocess.bind( self.postprocess_bind =
device, layouts
tgt_color_pp_view, .postprocess
sampler, .bind(device, tgt_color_pp_view, sampler, &self.postprocess);
&self.postprocess,
);
} }
} }
@ -920,7 +914,7 @@ impl Renderer {
pub fn start_recording_frame<'a>( pub fn start_recording_frame<'a>(
&'a mut self, &'a mut self,
globals: &'a GlobalsBindGroup, globals: &'a GlobalsBindGroup,
) -> Result<Option<Drawer<'a>>, RenderError> { ) -> Result<Option<drawer::Drawer<'a>>, RenderError> {
span!( span!(
_guard, _guard,
"start_recording_frame", "start_recording_frame",
@ -958,7 +952,7 @@ impl Renderer {
label: Some("A render encoder"), label: Some("A render encoder"),
}); });
Ok(Some(Drawer::new(encoder, self, tex, globals))) Ok(Some(drawer::Drawer::new(encoder, self, tex, globals)))
} }
/// Recreate the pipelines /// Recreate the pipelines
@ -2134,7 +2128,6 @@ fn create_pipelines(
device, device,
&create_shader("particle-vert", ShaderKind::Vertex)?, &create_shader("particle-vert", ShaderKind::Vertex)?,
&create_shader("particle-frag", ShaderKind::Fragment)?, &create_shader("particle-frag", ShaderKind::Fragment)?,
sc_desc,
&layouts.global, &layouts.global,
mode.aa, mode.aa,
); );

View File

@ -5,8 +5,8 @@ use super::{
instances::Instances, instances::Instances,
model::{DynamicModel, Model}, model::{DynamicModel, Model},
pipelines::{ pipelines::{
clouds, figure, fluid, postprocess, sprite, terrain, ui, GlobalsBindGroup, Light, clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup,
Shadow, Light, Shadow,
}, },
}, },
Renderer, Renderer,
@ -19,7 +19,6 @@ pub struct Drawer<'a> {
renderer: &'a mut Renderer, renderer: &'a mut Renderer,
tex: wgpu::SwapChainTexture, tex: wgpu::SwapChainTexture,
globals: &'a GlobalsBindGroup, globals: &'a GlobalsBindGroup,
//pub(super) postprocess_locals: wgpu::BindGroup,
} }
impl<'a> Drawer<'a> { impl<'a> Drawer<'a> {
@ -111,7 +110,7 @@ impl<'a> Drawer<'a> {
}, },
}], }],
// TODO: do we need this? // TODO: do we need this?
depth_stencil_attachment: None depth_stencil_attachment: None,
}); });
render_pass.set_bind_group(0, &self.globals.bind_group, &[]); render_pass.set_bind_group(0, &self.globals.bind_group, &[]);
@ -231,6 +230,36 @@ impl<'a> FirstPassDrawer<'a> {
self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0); self.render_pass.set_vertex_buffer(1, &instances.ibuf, 0, 0);
self.render_pass.draw(verts, 0..instances.count() as u32); self.render_pass.draw(verts, 0..instances.count() as u32);
}*/ }*/
pub fn draw_particles<'c>(&'c mut self) -> ParticleDrawer<'c, 'a> {
self.render_pass
.set_pipeline(&self.renderer.particle_pipeline.pipeline);
ParticleDrawer {
render_pass: &mut self.render_pass,
}
}
}
pub struct ParticleDrawer<'pass_ref, 'pass: 'pass_ref> {
render_pass: &'pass_ref mut wgpu::RenderPass<'pass>,
}
impl<'pass_ref, 'pass: 'pass_ref> ParticleDrawer<'pass_ref, 'pass> {
// Note: if we ever need to draw less than the whole model, this api can be
// changed
pub fn draw<'data: 'pass>(
&mut self,
model: &'data Model<particle::Vertex>,
instances: &'data Instances<particle::Instance>,
) {
self.render_pass.set_vertex_buffer(0, model.buf().slice(..));
self.render_pass
.set_vertex_buffer(1, instances.buf().slice(..));
self.render_pass
// TODO: since we cast to u32 maybe this should returned by the len/count functions?
.draw(0..model.len() as u32, 0..instances.count() as u32);
}
} }
pub struct SecondPassDrawer<'a> { pub struct SecondPassDrawer<'a> {
@ -262,7 +291,7 @@ impl<'a> ThirdPassDrawer<'a> {
self.render_pass.draw(0..3, 0..1); self.render_pass.draw(0..3, 0..1);
} }
pub fn draw_ui<'c>(&'c mut self) -> UiDrawer<'c, 'a> { pub fn draw_ui(&mut self) -> UiDrawer<'_, 'a> {
self.render_pass self.render_pass
.set_pipeline(&self.renderer.ui_pipeline.pipeline); .set_pipeline(&self.renderer.ui_pipeline.pipeline);

View File

@ -136,7 +136,7 @@ impl Camera {
self.dependents.view_mat_inv = self.dependents.view_mat.inverted(); self.dependents.view_mat_inv = self.dependents.view_mat.inverted();
self.dependents.proj_mat = self.dependents.proj_mat =
Mat4::perspective_rh_no(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE); Mat4::perspective_rh_zo(self.fov, self.aspect, NEAR_PLANE, FAR_PLANE);
self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted(); self.dependents.proj_mat_inv = self.dependents.proj_mat.inverted();
// TODO: Make this more efficient. // TODO: Make this more efficient.

View File

@ -16,8 +16,9 @@ pub use self::{
use crate::{ use crate::{
audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend}, audio::{ambient::AmbientMgr, music::MusicMgr, sfx::SfxMgr, AudioFrontend},
render::{ render::{
create_skybox_mesh, CloudsLocals, Consts, GlobalModel, Globals, GlobalsBindGroup, Light, create_skybox_mesh, CloudsLocals, Consts, FirstPassDrawer, GlobalModel, Globals,
Model, PostProcessLocals, Renderer, Shadow, ShadowLocals, SkyboxVertex, GlobalsBindGroup, Light, Model, PostProcessLocals, Renderer, Shadow, ShadowLocals,
SkyboxVertex,
}, },
settings::Settings, settings::Settings,
window::{AnalogGameInput, Event}, window::{AnalogGameInput, Event},
@ -976,9 +977,9 @@ impl Scene {
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
/// Render the scene using the provided `Renderer`. /// Render the scene using the provided `Renderer`.
pub fn render( pub fn render<'a>(
&mut self, &'a self,
renderer: &mut Renderer, drawer: &mut FirstPassDrawer<'a>,
state: &State, state: &State,
player_entity: EcsEntity, player_entity: EcsEntity,
tick: u64, tick: u64,
@ -995,7 +996,7 @@ impl Scene {
let camera_data = (&self.camera, scene_data.figure_lod_render_distance); let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
// would instead have this as an extension. // would instead have this as an extension.
if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) { /*if renderer.render_mode().shadow.is_map() && (is_daylight || !light_data.1.is_empty()) {
// if is_daylight { // if is_daylight {
// // Set up shadow mapping. // // Set up shadow mapping.
// renderer.start_shadows(); // renderer.start_shadows();
@ -1013,10 +1014,10 @@ impl Scene {
// // Flush shadows. // // Flush shadows.
// renderer.flush_shadows(); // renderer.flush_shadows();
// } // }
} }*/
let lod = self.lod.get_data(); let lod = self.lod.get_data();
self.figure_mgr.render_player( /*self.figure_mgr.render_player(
renderer, renderer,
state, state,
player_entity, player_entity,
@ -1024,10 +1025,10 @@ impl Scene {
global, global,
lod, lod,
camera_data, camera_data,
); );*/
// Render terrain and figures. // Render terrain and figures.
self.terrain.render(renderer, global, lod, focus_pos); /*self.terrain.render(renderer, global, lod, focus_pos);
self.figure_mgr.render( self.figure_mgr.render(
renderer, renderer,
@ -1038,21 +1039,22 @@ impl Scene {
lod, lod,
camera_data, camera_data,
); );
self.lod.render(renderer, global); self.lod.render(renderer, global);*/
// Render the skybox. // Render the skybox.
// TODO: renderer.render_skybox(&self.skybox.model, global, lod); // TODO: renderer.render_skybox(&self.skybox.model, global, lod);
self.terrain.render_translucent( /*self.terrain.render_translucent(
renderer, renderer,
global, global,
lod, lod,
focus_pos, focus_pos,
cam_pos, cam_pos,
scene_data.sprite_render_distance, scene_data.sprite_render_distance,
); );*/
// Render particle effects. // Render particle effects.
self.particle_mgr.render(renderer, scene_data, global, lod); self.particle_mgr
.render(&mut drawer.draw_particles(), scene_data);
} }
} }

View File

@ -3,7 +3,7 @@ use crate::{
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle}, mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle},
render::{ render::{
pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model, pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model,
ParticleInstance, ParticleVertex, Renderer, ParticleDrawer, ParticleInstance, ParticleVertex, Renderer,
}, },
}; };
use common::{ use common::{
@ -1178,13 +1178,7 @@ impl ParticleMgr {
self.instances = gpu_instances; self.instances = gpu_instances;
} }
pub fn render( pub fn render<'a>(&'a self, drawer: &mut ParticleDrawer<'_, 'a>, scene_data: &SceneData) {
&self,
renderer: &mut Renderer,
scene_data: &SceneData,
global: &GlobalModel,
lod: &LodData,
) {
span!(_guard, "render", "ParticleMgr::render"); span!(_guard, "render", "ParticleMgr::render");
if scene_data.particles_enabled { if scene_data.particles_enabled {
let model = &self let model = &self
@ -1192,8 +1186,7 @@ impl ParticleMgr {
.get(DEFAULT_MODEL_KEY) .get(DEFAULT_MODEL_KEY)
.expect("Expected particle model in cache"); .expect("Expected particle model in cache");
/* renderer.render_particles(model, global, &self.instances, drawer.draw(model, &self.instances);
* lod); */
} }
} }

View File

@ -1387,7 +1387,16 @@ impl PlayState for SessionState {
/// This method should be called once per frame. /// This method should be called once per frame.
fn render(&mut self, renderer: &mut Renderer, settings: &Settings) { fn render(&mut self, renderer: &mut Renderer, settings: &Settings) {
span!(_guard, "render", "<Session as PlayState>::render"); span!(_guard, "render", "<Session as PlayState>::render");
// Render the screen using the global renderer let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()
{
Some(d) => d,
// Couldn't get swap chain texture this frame
None => return,
};
// Render world
{ {
let client = self.client.borrow(); let client = self.client.borrow();
@ -1410,7 +1419,7 @@ impl PlayState for SessionState {
is_aiming: self.is_aiming, is_aiming: self.is_aiming,
}; };
self.scene.render( self.scene.render(
renderer, &mut drawer.first_pass(),
client.state(), client.state(),
client.entity(), client.entity(),
client.get_tick(), client.get_tick(),
@ -1418,18 +1427,6 @@ impl PlayState for SessionState {
); );
} }
let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()
{
Some(d) => d,
// Couldn't get swap chain texture this frame
None => return,
};
// Render world
/* let mut first_pass = */
drawer.first_pass();
// Clouds // Clouds
drawer.second_pass().draw_clouds(); drawer.second_pass().draw_clouds();
// PostProcess and UI // PostProcess and UI