Renable the figure and terrain drawing code (not working yet)

This commit is contained in:
Capucho 2020-12-06 15:34:25 +00:00 committed by Avi Weinstock
parent 3039bae635
commit f6300a6378
11 changed files with 161 additions and 141 deletions

View File

@ -37,9 +37,9 @@ layout(location = 1) flat in vec3 f_norm;
// const vec4 sun_pos = vec4(0.0);
// #endif
layout(set = 1, binding = 2)
layout(set = 2, binding = 0)
uniform texture2D t_col_light;
layout(set = 1, binding = 3)
layout(set = 2, binding = 1)
uniform sampler s_col_light;
//struct ShadowLocals {

View File

@ -237,13 +237,9 @@ impl PlayState for CharSelectionState {
let (humanoid_body, loadout) =
Self::get_humanoid_body_inventory(&self.char_selection_ui, &client);
// Render the scene.
//self.scene
// .render(renderer, client.get_tick(), humanoid_body, loadout);
self.scene
.render(&mut drawer.first_pass(), client.get_tick(), humanoid_body, loadout);
// Render world
/* let mut first_pass = */
drawer.first_pass();
// Clouds
drawer.second_pass().draw_clouds();
// PostProcess and UI

View File

@ -13,7 +13,8 @@ pub struct SubModel<'a, V: Vertex> {
}
impl<'a, V: Vertex> SubModel<'a, V> {
pub(super) fn buf(&self) -> &wgpu::Buffer { self.buf }
pub(super) fn buf(&self) -> wgpu::BufferSlice<'a> { self.buf.slice(map_range(&self.vertex_range)) }
pub fn len(&self) -> u32 { self.vertex_range.end - self.vertex_range.start }
}
/// Represents a mesh that has been sent to the GPU.
@ -79,3 +80,5 @@ impl<V: Vertex> DynamicModel<V> {
pub fn len(&self) -> usize { self.vbuf.len() }
}
fn map_range(range: &Range<u32>) -> Range<u64> { (range.start as u64)..(range.end as u64) }

View File

@ -144,6 +144,7 @@ impl CloudsPipeline {
vs_module: &wgpu::ShaderModule,
fs_module: &wgpu::ShaderModule,
global_layout: &GlobalsLayouts,
sc_desc: &wgpu::SwapChainDescriptor,
layout: &CloudsLayout,
aa_mode: AaMode,
) -> Self {
@ -177,7 +178,7 @@ impl CloudsPipeline {
rasterization_state: None,
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor {
format: wgpu::TextureFormat::Rgba8UnormSrgb,
format: sc_desc.format,
color_blend: wgpu::BlendDescriptor::REPLACE,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,

View File

@ -1,5 +1,5 @@
use super::{
super::{AaMode, GlobalsLayouts, Mesh, Model},
super::{AaMode, Bound, Consts, GlobalsLayouts, Mesh, Model, Texture},
terrain::Vertex,
};
use crate::mesh::greedy::GreedyMesh;
@ -25,6 +25,9 @@ pub struct BoneData {
normals_mat: [[f32; 4]; 4],
}
pub type BoundLocals = Bound<(Consts<Locals>, Consts<BoneData>)>;
pub type ColLights = Bound<Texture>;
impl Locals {
pub fn new(
model_mat: anim::vek::Mat4<f32>,
@ -99,6 +102,7 @@ pub type BoneMeshes = (Mesh<Vertex>, anim::vek::Aabb<f32>);
pub struct FigureLayout {
pub locals: wgpu::BindGroupLayout,
pub col_light: wgpu::BindGroupLayout,
}
impl FigureLayout {
@ -129,9 +133,14 @@ impl FigureLayout {
},
count: None,
},
],
}),
col_light: device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
entries: &[
// col lights
wgpu::BindGroupLayoutEntry {
binding: 2,
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: true },
@ -141,15 +150,67 @@ impl FigureLayout {
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 3,
binding: 1,
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,
},
],
}),
}
}
pub fn bind_locals(
&self,
device: &wgpu::Device,
locals: Consts<Locals>,
bone_data: Consts<BoneData>,
) -> BoundLocals {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.locals,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: locals.buf().as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: bone_data.buf().as_entire_binding(),
},
],
});
BoundLocals {
bind_group,
with: (locals, bone_data),
}
}
pub fn bind_texture(&self, device: &wgpu::Device, col_light: Texture) -> ColLights {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.col_light,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(&col_light.view),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Sampler(&col_light.sampler),
},
],
});
ColLights {
bind_group,
with: col_light,
}
}
}
pub struct FigurePipeline {
@ -171,7 +232,7 @@ impl FigurePipeline {
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Figure pipeline layout"),
push_constant_ranges: &[],
bind_group_layouts: &[&global_layout.globals, &layout.locals],
bind_group_layouts: &[&global_layout.globals, &layout.locals, &layout.col_light],
});
let samples = match aa_mode {

View File

@ -1,4 +1,4 @@
use super::super::{AaMode, GlobalsLayouts};
use super::super::{AaMode, Bound, Consts, GlobalsLayouts};
use bytemuck::{Pod, Zeroable};
use vek::*;
@ -149,6 +149,8 @@ impl Locals {
}
}
pub type BoundLocals = Bound<Consts<Locals>>;
pub struct TerrainLayout {
pub locals: wgpu::BindGroupLayout,
}

View File

@ -612,13 +612,13 @@ impl Renderer {
mip_level_count: levels,
sample_count,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::RENDER_ATTACHMENT,
});
tex.create_view(&wgpu::TextureViewDescriptor {
label: None,
format: Some(wgpu::TextureFormat::Rgba8UnormSrgb),
format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
dimension: Some(wgpu::TextureViewDimension::D2),
// TODO: why is this not Color?
aspect: wgpu::TextureAspect::All,
@ -2160,6 +2160,7 @@ fn create_pipelines(
&create_shader("clouds-frag", ShaderKind::Fragment)?,
// TODO: pass in format of intermediate color buffer
&layouts.global,
sc_desc,
&layouts.clouds,
mode.aa,
);

View File

@ -1,7 +1,7 @@
use super::{
super::{
consts::Consts,
pipelines::{lod_terrain, ui, GlobalModel, GlobalsBindGroup},
pipelines::{figure, lod_terrain, ui, GlobalModel, GlobalsBindGroup},
texture::Texture,
},
Renderer,
@ -36,4 +36,20 @@ impl Renderer {
pub fn ui_bind_texture(&self, texture: &Texture) -> ui::TextureBindGroup {
self.layouts.ui.bind_texture(&self.device, texture)
}
pub fn create_figure_bound_locals(
&mut self,
locals: &[figure::Locals],
bone_data: &[figure::BoneData],
) -> figure::BoundLocals {
let locals = self.create_consts(locals);
let bone_data = self.create_consts(bone_data);
self.layouts
.figure
.bind_locals(&self.device, locals, bone_data)
}
pub fn figure_bind_texture(&self, col_light: Texture) -> figure::ColLights {
self.layouts.figure.bind_texture(&self.device, col_light)
}
}

View File

@ -3,7 +3,7 @@ use super::{
buffer::Buffer,
consts::Consts,
instances::Instances,
model::{DynamicModel, Model},
model::{DynamicModel, SubModel,Model},
pipelines::{
clouds, figure, fluid, particle, postprocess, sprite, terrain, ui, GlobalsBindGroup,
Light, Shadow,
@ -109,7 +109,6 @@ impl<'a> Drawer<'a> {
store: true,
},
}],
// TODO: do we need this?
depth_stencil_attachment: None,
});
@ -149,49 +148,37 @@ impl<'a> FirstPassDrawer<'a> {
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
}
}*/
pub fn draw_figure<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<figure::Locals>,
bones: &'b Consts<figure::BoneData>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
model: SubModel<'b, terrain::Vertex>,
locals: &'b figure::BoundLocals,
col_lights: &'b figure::ColLights
) {
self.render_pass
.set_pipeline(&self.renderer.figure_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.set_bind_group(4, &bones.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1);
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
self.render_pass.set_bind_group(2, &col_lights.bind_group, &[]);
self.render_pass
.set_vertex_buffer(0, model.buf());
self.render_pass.draw(0..model.len(), 0..1);
}
pub fn draw_terrain<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<terrain::Locals>,
globals: &'b Consts<Globals>,
lights: &'b Consts<Light>,
shadows: &'b Consts<Shadow>,
verts: Range<u32>,
model: &'b SubModel<terrain::Vertex>,
locals: &'b terrain::BoundLocals,
) {
self.render_pass
.set_pipeline(&self.renderer.terrain_pipeline.pipeline);
self.render_pass.set_bind_group(0, &globals.bind_group, &[]);
self.render_pass.set_bind_group(1, &lights.bind_group, &[]);
self.render_pass.set_bind_group(2, &shadows.bind_group, &[]);
self.render_pass.set_bind_group(3, &locals.bind_group, &[]);
self.render_pass.set_vertex_buffer(0, &model.vbuf, 0, 0);
self.render_pass.draw(verts, 0..1)
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
self.render_pass
.set_vertex_buffer(0, model.buf());
self.render_pass.draw(0..model.len(), 0..1)
}
pub fn draw_fluid<'b: 'a>(
/*pub fn draw_fluid<'b: 'a>(
&mut self,
model: &'b Model,
locals: &'b Consts<terrain::Locals>,

View File

@ -61,8 +61,7 @@ pub type CameraData<'a> = (&'a Camera, f32);
/// Enough data to render a figure model.
pub type FigureModelRef<'a> = (
&'a Consts<FigureLocals>,
&'a Consts<FigureBoneData>,
&'a pipelines::figure::BoundLocals,
SubModel<'a, TerrainVertex>,
&'a Texture, /* <ColLightFmt> */
);
@ -80,7 +79,7 @@ pub struct FigureModelEntry<const N: usize> {
/// Texture used to store color/light information for this figure entry.
/* TODO: Consider using mipmaps instead of storing multiple texture atlases for different
* LOD levels. */
col_lights: Texture, /* <ColLightFmt> */
col_lights: pipelines::figure::ColLights,
/// Vertex ranges stored in this figure entry; there may be several for one
/// figure, because of LOD models.
lod_vertex_ranges: [Range<u32>; N],
@ -4732,7 +4731,7 @@ impl FigureMgr {
// Don't render dead entities
.filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead))
.for_each(|(entity, pos, _, body, _, inventory, scale)| {
if let Some((locals, bone_consts, model, _)) = self.get_model_for_render(
if let Some((bound, model, _)) = self.get_model_for_render(
tick,
camera,
None,
@ -4790,7 +4789,7 @@ impl FigureMgr {
let is_player = entity == player_entity;
if !is_player {
if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render(
if let Some((bound, model, col_lights)) = self.get_model_for_render(
tick,
camera,
character_state,
@ -4839,7 +4838,7 @@ impl FigureMgr {
let inventory_storage = ecs.read_storage::<Inventory>();
let inventory = inventory_storage.get(player_entity);
if let Some((locals, bone_consts, model, col_lights)) = self.get_model_for_render(
if let Some((bound, model, col_lights)) = self.get_model_for_render(
tick,
camera,
character_state,
@ -4925,14 +4924,13 @@ impl FigureMgr {
},
} = self;
let col_lights = &*col_lights_;
if let Some((locals, bone_consts, model_entry)) = match body {
if let Some((bound, model_entry)) = match body {
Body::Humanoid(body) => character_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
model_cache.get_model(
col_lights,
*body,
@ -4948,8 +4946,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
quadruped_small_model_cache.get_model(
col_lights,
*body,
@ -4965,8 +4962,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
quadruped_medium_model_cache.get_model(
col_lights,
*body,
@ -4982,8 +4978,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
quadruped_low_model_cache.get_model(
col_lights,
*body,
@ -4999,8 +4994,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
bird_medium_model_cache.get_model(
col_lights,
*body,
@ -5016,8 +5010,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
fish_medium_model_cache.get_model(
col_lights,
*body,
@ -5033,8 +5026,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
theropod_model_cache.get_model(
col_lights,
*body,
@ -5050,8 +5042,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
dragon_model_cache.get_model(
col_lights,
*body,
@ -5067,8 +5058,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
bird_large_model_cache.get_model(
col_lights,
*body,
@ -5084,8 +5074,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
fish_small_model_cache.get_model(
col_lights,
*body,
@ -5101,8 +5090,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
biped_large_model_cache.get_model(
col_lights,
*body,
@ -5118,8 +5106,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
biped_small_model_cache.get_model(
col_lights,
*body,
@ -5135,8 +5122,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
golem_model_cache.get_model(
col_lights,
*body,
@ -5152,8 +5138,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
object_model_cache.get_model(
col_lights,
*body,
@ -5169,8 +5154,7 @@ impl FigureMgr {
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
state.bound(),
ship_model_cache.get_model(
col_lights,
*body,
@ -5195,7 +5179,7 @@ impl FigureMgr {
model_entry.lod_model(0)
};
Some((locals, bone_consts, model, col_lights_.texture(model_entry)))
Some((bound, model, col_lights_.texture(model_entry)))
} else {
// trace!("Body has no saved figure");
None
@ -5221,8 +5205,10 @@ impl FigureColLights {
}
/// Find the correct texture for this model entry.
pub fn texture<'a, const N: usize>(&'a self, model: &'a FigureModelEntry<N>) -> &'a Texture /* <ColLightFmt> */
{
pub fn texture<'a, const N: usize>(
&'a self,
model: &'a FigureModelEntry<N>,
) -> &'a pipelines::figure::ColLights {
/* &self.col_lights */
&model.col_lights
}
@ -5246,6 +5232,7 @@ impl FigureColLights {
.allocate(guillotiere::Size::new(tex_size.x as i32, tex_size.y as i32))
.expect("Not yet implemented: allocate new atlas on allocation failure.");
let col_lights = pipelines::shadow::create_col_lights(renderer, &(tex, tex_size));
let col_lights = renderer.figure_bind_texture(col_lights);
let model_len = u32::try_from(opaque.vertices().len())
.expect("The model size for this figure does not fit in a u32!");
let model = renderer.create_model(&opaque)?;
@ -5305,8 +5292,6 @@ impl FigureColLights {
}
pub struct FigureStateMeta {
bone_consts: Consts<FigureBoneData>,
locals: Consts<FigureLocals>,
lantern_offset: anim::vek::Vec3<f32>,
state_time: f32,
last_ori: anim::vek::Quaternion<f32>,
@ -5318,6 +5303,7 @@ pub struct FigureStateMeta {
last_light: f32,
last_glow: (Vec3<f32>, f32),
acc_vel: f32,
bound: pipelines::figure::BoundLocals,
}
impl FigureStateMeta {
@ -5352,8 +5338,6 @@ impl<S: Skeleton> FigureState<S> {
let bone_consts = figure_bone_data_from_anim(&buf);
Self {
meta: FigureStateMeta {
bone_consts: renderer.create_consts(bone_consts),
locals: renderer.create_consts(&[FigureLocals::default()]),
lantern_offset,
state_time: 0.0,
last_ori: Ori::default().into(),
@ -5365,6 +5349,7 @@ impl<S: Skeleton> FigureState<S> {
last_light: 1.0,
last_glow: (Vec3::zero(), 0.0),
acc_vel: 0.0,
bound: renderer.create_figure_bound_locals(&[FigureLocals::default()], bone_consts),
},
skeleton,
}
@ -5476,16 +5461,13 @@ impl<S: Skeleton> FigureState<S> {
self.last_light,
self.last_glow,
);
renderer.update_consts(&mut self.locals, &[locals]);
renderer.update_consts(&mut self.meta.bound.0, &[locals]);
let lantern_offset = anim::compute_matrices(&self.skeleton, mat, buf);
let new_bone_consts = figure_bone_data_from_anim(buf);
renderer.update_consts(
&mut self.meta.bone_consts,
&new_bone_consts[0..S::BONE_COUNT],
);
renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]);
self.lantern_offset = lantern_offset;
let smoothing = (5.0 * dt).min(1.0);
@ -5502,9 +5484,7 @@ impl<S: Skeleton> FigureState<S> {
}
}
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }
pub fn bone_consts(&self) -> &Consts<FigureBoneData> { &self.bone_consts }
pub fn bound(&self) -> &pipelines::figure::BoundLocals { &self.bound }
pub fn skeleton_mut(&mut self) -> &mut S { &mut self.skeleton }
}

View File

@ -1,7 +1,7 @@
use crate::{
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
render::{
create_skybox_mesh, BoneMeshes, Consts, FigureModel, GlobalModel, Globals,
create_skybox_mesh, BoneMeshes, Consts, FigureModel, FirstPassDrawer, GlobalModel, Globals,
GlobalsBindGroup, Light, LodData, Mesh, Model, Renderer, Shadow, ShadowLocals,
SkyboxVertex, TerrainVertex,
},
@ -346,20 +346,13 @@ impl Scene {
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
pub fn render(
&mut self,
renderer: &mut Renderer,
pub fn render<'a>(
&'a self,
drawer: &mut FirstPassDrawer<'a>,
tick: u64,
body: Option<humanoid::Body>,
inventory: Option<&Inventory>,
) {
/*renderer.render_skybox(
&self.skybox.model,
&self.data,
&self.skybox.locals,
&self.lod,
);*/
if let Some(body) = body {
let model = &self.figure_model_cache.get_model(
&self.col_lights,
@ -371,40 +364,20 @@ impl Scene {
);
if let Some(model) = model {
// renderer.render_figure(
// &model.models[0],
// &self.col_lights.texture(model),
// &self.data,
// self.figure_state.locals(),
// self.figure_state.bone_consts(),
// &self.lod,
// );
drawer.draw_figure(
model.lod_model(0),
self.figure_state.bound(),
&self.col_lights.texture(model),
);
}
}
if let Some((model, state)) = &self.backdrop {
/*renderer.render_figure(
&model.models[0],
drawer.draw_figure(
model.lod_model(0),
state.bound(),
&self.col_lights.texture(model),
&self.data,
state.locals(),
state.bone_consts(),
&self.lod,
);*/
);
}
// renderer.render_clouds(
// &self.clouds.model,
// &self.data.globals,
// &self.clouds.locals,
// &self.lod,
// );
// renderer.render_post_process(
// &self.postprocess.model,
// &self.data.globals,
// &self.postprocess.locals,
// &self.lod,
// );
}
}