|
|
|
@ -5,7 +5,7 @@ use strafesnet_settings::settings;
|
|
|
|
|
use strafesnet_session::session;
|
|
|
|
|
use strafesnet_common::model::{self, ColorId, NormalId, PolygonIter, PositionId, RenderConfigId, TextureCoordinateId, VertexId};
|
|
|
|
|
use wgpu::{util::DeviceExt,AstcBlock,AstcChannel};
|
|
|
|
|
use crate::model::{self as model_graphics,IndexedGraphicsMeshOwnedRenderConfig,IndexedGraphicsMeshOwnedRenderConfigId,GraphicsMeshOwnedRenderConfig,GraphicsModelColor4,GraphicsModelOwned,GraphicsVertex};
|
|
|
|
|
use crate::model::{self as model_graphics,IndexedGraphicsMeshOwnedRenderConfig,IndexedGraphicsMeshOwnedRenderConfigId,GraphicsMeshOwnedRenderConfig,GraphicsModelColor4,GraphicsModelOwned,GraphicsVertex,DebugGraphicsVertex};
|
|
|
|
|
|
|
|
|
|
pub fn required_limits()->wgpu::Limits{
|
|
|
|
|
wgpu::Limits::default()
|
|
|
|
@ -36,12 +36,22 @@ struct GraphicsModel{
|
|
|
|
|
instance_count:u32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct DebugGraphicsMesh{
|
|
|
|
|
indices:Indices,
|
|
|
|
|
vertex_buf:wgpu::Buffer,
|
|
|
|
|
}
|
|
|
|
|
struct DebugGraphicsModel{
|
|
|
|
|
debug_mesh_id:u32,
|
|
|
|
|
bind_group:wgpu::BindGroup,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct GraphicsSamplers{
|
|
|
|
|
repeat:wgpu::Sampler,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct GraphicsBindGroupLayouts{
|
|
|
|
|
model:wgpu::BindGroupLayout,
|
|
|
|
|
debug_model:wgpu::BindGroupLayout,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct GraphicsBindGroups{
|
|
|
|
@ -52,6 +62,7 @@ struct GraphicsBindGroups{
|
|
|
|
|
struct GraphicsPipelines{
|
|
|
|
|
skybox:wgpu::RenderPipeline,
|
|
|
|
|
model:wgpu::RenderPipeline,
|
|
|
|
|
debug:wgpu::RenderPipeline,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct GraphicsCamera{
|
|
|
|
@ -112,6 +123,8 @@ pub struct GraphicsState{
|
|
|
|
|
camera_buf:wgpu::Buffer,
|
|
|
|
|
temp_squid_texture_view:wgpu::TextureView,
|
|
|
|
|
models:Vec<GraphicsModel>,
|
|
|
|
|
debug_meshes:Vec<DebugGraphicsMesh>,
|
|
|
|
|
debug_models:Vec<DebugGraphicsModel>,
|
|
|
|
|
depth_view:wgpu::TextureView,
|
|
|
|
|
staging_belt:wgpu::util::StagingBelt,
|
|
|
|
|
}
|
|
|
|
@ -146,6 +159,76 @@ impl GraphicsState{
|
|
|
|
|
self.camera.fov=user_settings.calculate_fov(1.0,&self.camera.screen_size).as_vec2();
|
|
|
|
|
}
|
|
|
|
|
pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:&map::CompleteMap){
|
|
|
|
|
//generate debug meshes, each debug model refers to one
|
|
|
|
|
self.debug_meshes=map.meshes.iter().map(|mesh|{
|
|
|
|
|
let vertices:Vec<DebugGraphicsVertex>=mesh.unique_vertices.iter().map(|vertex|{
|
|
|
|
|
DebugGraphicsVertex{
|
|
|
|
|
pos:mesh.unique_pos[vertex.pos.get() as usize].to_array().map(Into::into),
|
|
|
|
|
normal:mesh.unique_normal[vertex.normal.get() as usize].to_array().map(Into::into),
|
|
|
|
|
}
|
|
|
|
|
}).collect();
|
|
|
|
|
let vertex_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
|
|
|
|
|
label:Some("Vertex"),
|
|
|
|
|
contents:bytemuck::cast_slice(&vertices),
|
|
|
|
|
usage:wgpu::BufferUsages::VERTEX,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let mut indices=Vec::new();
|
|
|
|
|
for physics_group in &mesh.physics_groups{
|
|
|
|
|
for polygon_group_id in &physics_group.groups{
|
|
|
|
|
for poly in mesh.polygon_groups[polygon_group_id.get() as usize].polys(){
|
|
|
|
|
// triangulate
|
|
|
|
|
let mut poly_vertices=poly.into_iter().copied();
|
|
|
|
|
if let (Some(a),Some(mut b))=(poly_vertices.next(),poly_vertices.next()){
|
|
|
|
|
for c in poly_vertices{
|
|
|
|
|
indices.extend([a,b,c]);
|
|
|
|
|
b=c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DebugGraphicsMesh{
|
|
|
|
|
indices:if (u32::MAX as usize)<vertices.len(){
|
|
|
|
|
panic!("Model has too many vertices!")
|
|
|
|
|
}else if (u16::MAX as usize)<vertices.len(){
|
|
|
|
|
Indices::new(device,&indices.into_iter().map(|vertex_idx|vertex_idx.get() as u32).collect(),wgpu::IndexFormat::Uint32)
|
|
|
|
|
}else{
|
|
|
|
|
Indices::new(device,&indices.into_iter().map(|vertex_idx|vertex_idx.get() as u16).collect(),wgpu::IndexFormat::Uint16)
|
|
|
|
|
},
|
|
|
|
|
vertex_buf,
|
|
|
|
|
}
|
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
|
|
//generate debug models, only one will be rendered at a time
|
|
|
|
|
self.debug_models=map.models.iter().enumerate().map(|(model_id,model)|{
|
|
|
|
|
let model_uniforms=get_instance_buffer_data(&GraphicsModelOwned{
|
|
|
|
|
transform:model.transform.into(),
|
|
|
|
|
normal_transform:glam::Mat3::from_cols_array_2d(&model.transform.matrix3.to_array().map(|row|row.map(Into::into))).inverse().transpose(),
|
|
|
|
|
color:GraphicsModelColor4::new(glam::vec4(1.0,0.0,0.0,0.2)),
|
|
|
|
|
});
|
|
|
|
|
let model_buf=device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
|
|
|
|
|
label:Some(format!("Debug Model{} Buf",model_id).as_str()),
|
|
|
|
|
contents:bytemuck::cast_slice(&model_uniforms),
|
|
|
|
|
usage:wgpu::BufferUsages::UNIFORM|wgpu::BufferUsages::COPY_DST,
|
|
|
|
|
});
|
|
|
|
|
let bind_group=device.create_bind_group(&wgpu::BindGroupDescriptor{
|
|
|
|
|
layout:&self.bind_group_layouts.debug_model,
|
|
|
|
|
entries:&[
|
|
|
|
|
wgpu::BindGroupEntry{
|
|
|
|
|
binding:0,
|
|
|
|
|
resource:model_buf.as_entire_binding(),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
label:Some(format!("Debug Model{} Bind Group",model_id).as_str()),
|
|
|
|
|
});
|
|
|
|
|
DebugGraphicsModel{
|
|
|
|
|
debug_mesh_id:model.mesh.get(),
|
|
|
|
|
bind_group,
|
|
|
|
|
}
|
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
|
|
//generate texture view per texture
|
|
|
|
|
let texture_views:HashMap<strafesnet_common::model::TextureId,wgpu::TextureView>=map.textures.iter().enumerate().filter_map(|(texture_id,texture_data)|{
|
|
|
|
|
let texture_id=model::TextureId::new(texture_id as u32);
|
|
|
|
@ -588,6 +671,21 @@ impl GraphicsState{
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
let debug_model_bind_group_layout=device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor{
|
|
|
|
|
label:Some("Debug Model Bind Group Layout"),
|
|
|
|
|
entries:&[
|
|
|
|
|
wgpu::BindGroupLayoutEntry{
|
|
|
|
|
binding:0,
|
|
|
|
|
visibility:wgpu::ShaderStages::VERTEX_FRAGMENT,
|
|
|
|
|
ty:wgpu::BindingType::Buffer{
|
|
|
|
|
ty:wgpu::BufferBindingType::Uniform,
|
|
|
|
|
has_dynamic_offset:false,
|
|
|
|
|
min_binding_size:None,
|
|
|
|
|
},
|
|
|
|
|
count:None,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let clamp_sampler=device.create_sampler(&wgpu::SamplerDescriptor{
|
|
|
|
|
label:Some("Clamp Sampler"),
|
|
|
|
@ -736,6 +834,14 @@ impl GraphicsState{
|
|
|
|
|
],
|
|
|
|
|
push_constant_ranges:&[],
|
|
|
|
|
});
|
|
|
|
|
let debug_model_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
|
|
|
|
label:None,
|
|
|
|
|
bind_group_layouts:&[
|
|
|
|
|
&camera_bind_group_layout,
|
|
|
|
|
&debug_model_bind_group_layout,
|
|
|
|
|
],
|
|
|
|
|
push_constant_ranges:&[],
|
|
|
|
|
});
|
|
|
|
|
let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
|
|
|
|
label:None,
|
|
|
|
|
bind_group_layouts:&[
|
|
|
|
@ -811,6 +917,45 @@ impl GraphicsState{
|
|
|
|
|
multiview:None,
|
|
|
|
|
cache:None,
|
|
|
|
|
});
|
|
|
|
|
let debug_model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{
|
|
|
|
|
label:Some("Debug Model Pipeline"),
|
|
|
|
|
layout:Some(&debug_model_pipeline_layout),
|
|
|
|
|
vertex:wgpu::VertexState{
|
|
|
|
|
module:&shader,
|
|
|
|
|
entry_point:Some("vs_debug"),
|
|
|
|
|
buffers:&[wgpu::VertexBufferLayout{
|
|
|
|
|
array_stride:std::mem::size_of::<DebugGraphicsVertex>() as wgpu::BufferAddress,
|
|
|
|
|
step_mode:wgpu::VertexStepMode::Vertex,
|
|
|
|
|
attributes:&wgpu::vertex_attr_array![0=>Float32x3,1=>Float32x3],
|
|
|
|
|
}],
|
|
|
|
|
compilation_options:wgpu::PipelineCompilationOptions::default(),
|
|
|
|
|
},
|
|
|
|
|
fragment:Some(wgpu::FragmentState{
|
|
|
|
|
module:&shader,
|
|
|
|
|
entry_point:Some("fs_debug"),
|
|
|
|
|
targets:&[Some(wgpu::ColorTargetState{
|
|
|
|
|
format:config.view_formats[0],
|
|
|
|
|
blend:Some(wgpu::BlendState::ALPHA_BLENDING),
|
|
|
|
|
write_mask:wgpu::ColorWrites::default(),
|
|
|
|
|
})],
|
|
|
|
|
compilation_options:wgpu::PipelineCompilationOptions::default(),
|
|
|
|
|
}),
|
|
|
|
|
primitive:wgpu::PrimitiveState{
|
|
|
|
|
front_face:wgpu::FrontFace::Cw,
|
|
|
|
|
cull_mode:Some(wgpu::Face::Front),
|
|
|
|
|
..Default::default()
|
|
|
|
|
},
|
|
|
|
|
depth_stencil:Some(wgpu::DepthStencilState{
|
|
|
|
|
format:Self::DEPTH_FORMAT,
|
|
|
|
|
depth_write_enabled:true,
|
|
|
|
|
depth_compare:wgpu::CompareFunction::Always,
|
|
|
|
|
stencil:wgpu::StencilState::default(),
|
|
|
|
|
bias:wgpu::DepthBiasState::default(),
|
|
|
|
|
}),
|
|
|
|
|
multisample:wgpu::MultisampleState::default(),
|
|
|
|
|
multiview:None,
|
|
|
|
|
cache:None,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let camera=GraphicsCamera::default();
|
|
|
|
|
let camera_uniforms=camera.to_uniform_data(glam::Vec3::ZERO,glam::Vec2::ZERO);
|
|
|
|
@ -850,7 +995,8 @@ impl GraphicsState{
|
|
|
|
|
Self{
|
|
|
|
|
pipelines:GraphicsPipelines{
|
|
|
|
|
skybox:sky_pipeline,
|
|
|
|
|
model:model_pipeline
|
|
|
|
|
model:model_pipeline,
|
|
|
|
|
debug:debug_model_pipeline,
|
|
|
|
|
},
|
|
|
|
|
bind_groups:GraphicsBindGroups{
|
|
|
|
|
camera:camera_bind_group,
|
|
|
|
@ -859,9 +1005,14 @@ impl GraphicsState{
|
|
|
|
|
camera,
|
|
|
|
|
camera_buf,
|
|
|
|
|
models:Vec::new(),
|
|
|
|
|
debug_meshes:Vec::new(),
|
|
|
|
|
debug_models:Vec::new(),
|
|
|
|
|
depth_view,
|
|
|
|
|
staging_belt:wgpu::util::StagingBelt::new(0x100),
|
|
|
|
|
bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout},
|
|
|
|
|
bind_group_layouts:GraphicsBindGroupLayouts{
|
|
|
|
|
model:model_bind_group_layout,
|
|
|
|
|
debug_model:debug_model_bind_group_layout,
|
|
|
|
|
},
|
|
|
|
|
samplers:GraphicsSamplers{repeat:repeat_sampler},
|
|
|
|
|
temp_squid_texture_view:squid_texture_view,
|
|
|
|
|
}
|
|
|
|
@ -949,6 +1100,7 @@ impl GraphicsState{
|
|
|
|
|
rpass.set_bind_group(0,&self.bind_groups.camera,&[]);
|
|
|
|
|
rpass.set_bind_group(1,&self.bind_groups.skybox_texture,&[]);
|
|
|
|
|
|
|
|
|
|
// Draw all models.
|
|
|
|
|
rpass.set_pipeline(&self.pipelines.model);
|
|
|
|
|
for model in &self.models{
|
|
|
|
|
rpass.set_bind_group(2,&model.bind_group,&[]);
|
|
|
|
@ -960,6 +1112,19 @@ impl GraphicsState{
|
|
|
|
|
|
|
|
|
|
rpass.set_pipeline(&self.pipelines.skybox);
|
|
|
|
|
rpass.draw(0..3,0..1);
|
|
|
|
|
|
|
|
|
|
// render a single debug_model in red
|
|
|
|
|
if let Some(model_id)=frame_state.debug_model{
|
|
|
|
|
if let Some(model)=self.debug_models.get(model_id.get() as usize){
|
|
|
|
|
let mesh=&self.debug_meshes[model.debug_mesh_id as usize];
|
|
|
|
|
rpass.set_pipeline(&self.pipelines.debug);
|
|
|
|
|
rpass.set_bind_group(1,&model.bind_group,&[]);
|
|
|
|
|
rpass.set_vertex_buffer(0,mesh.vertex_buf.slice(..));
|
|
|
|
|
rpass.set_index_buffer(mesh.indices.buf.slice(..),mesh.indices.format);
|
|
|
|
|
//TODO: loop over triangle strips
|
|
|
|
|
rpass.draw_indexed(0..mesh.indices.count,0,0..1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue.submit(std::iter::once(encoder.finish()));
|
|
|
|
@ -968,21 +1133,23 @@ impl GraphicsState{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const MODEL_BUFFER_SIZE:usize=4*4 + 12 + 4;//let size=std::mem::size_of::<ModelInstance>();
|
|
|
|
|
const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*4;
|
|
|
|
|
const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*core::mem::size_of::<f32>();
|
|
|
|
|
fn get_instance_buffer_data(instance:&GraphicsModelOwned)->[f32;MODEL_BUFFER_SIZE]{
|
|
|
|
|
let mut out=[0.0;MODEL_BUFFER_SIZE];
|
|
|
|
|
out[0..16].copy_from_slice(instance.transform.as_ref());
|
|
|
|
|
out[16..19].copy_from_slice(instance.normal_transform.x_axis.as_ref());
|
|
|
|
|
// out[20]=0.0;
|
|
|
|
|
out[20..23].copy_from_slice(instance.normal_transform.y_axis.as_ref());
|
|
|
|
|
// out[24]=0.0;
|
|
|
|
|
out[24..27].copy_from_slice(instance.normal_transform.z_axis.as_ref());
|
|
|
|
|
// out[28]=0.0;
|
|
|
|
|
out[28..32].copy_from_slice(instance.color.get().as_ref());
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
fn get_instances_buffer_data(instances:&[GraphicsModelOwned])->Vec<f32>{
|
|
|
|
|
let mut raw=Vec::with_capacity(MODEL_BUFFER_SIZE*instances.len());
|
|
|
|
|
for mi in instances{
|
|
|
|
|
//model transform
|
|
|
|
|
raw.extend_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&mi.transform)[..]);
|
|
|
|
|
//normal transform
|
|
|
|
|
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.x_axis));
|
|
|
|
|
raw.extend_from_slice(&[0.0]);
|
|
|
|
|
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.y_axis));
|
|
|
|
|
raw.extend_from_slice(&[0.0]);
|
|
|
|
|
raw.extend_from_slice(AsRef::<[f32; 3]>::as_ref(&mi.normal_transform.z_axis));
|
|
|
|
|
raw.extend_from_slice(&[0.0]);
|
|
|
|
|
//color
|
|
|
|
|
raw.extend_from_slice(AsRef::<[f32; 4]>::as_ref(&mi.color.get()));
|
|
|
|
|
raw.extend_from_slice(&get_instance_buffer_data(mi));
|
|
|
|
|
}
|
|
|
|
|
raw
|
|
|
|
|
}
|
|
|
|
|