Add placeholder fog volume
This commit is contained in:
parent
4b03671a62
commit
ca9ed36c37
5 changed files with 227 additions and 23 deletions
46
res/shaders/fog.wgsl
Normal file
46
res/shaders/fog.wgsl
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include globals.wgsl
|
||||||
|
|
||||||
|
@vertex
|
||||||
|
fn vs_main(
|
||||||
|
model: VertexInput,
|
||||||
|
instance: InstanceInput,
|
||||||
|
) -> VertexOutput {
|
||||||
|
let model_matrix = mat4x4<f32>(
|
||||||
|
instance.model_matrix_0,
|
||||||
|
instance.model_matrix_1,
|
||||||
|
instance.model_matrix_2,
|
||||||
|
instance.model_matrix_3,
|
||||||
|
);
|
||||||
|
let normal_matrix = mat3x3<f32>(
|
||||||
|
instance.normal_matrix_0,
|
||||||
|
instance.normal_matrix_1,
|
||||||
|
instance.normal_matrix_2,
|
||||||
|
);
|
||||||
|
|
||||||
|
let world_normal = normalize(normal_matrix * model.normal);
|
||||||
|
let world_tangent = normalize(normal_matrix * model.tangent);
|
||||||
|
let world_bitangent = normalize(normal_matrix * model.bitangent);
|
||||||
|
let tangent_matrix = transpose(mat3x3<f32>(
|
||||||
|
world_tangent,
|
||||||
|
world_bitangent,
|
||||||
|
world_normal,
|
||||||
|
));
|
||||||
|
|
||||||
|
let world_position = model_matrix * vec4<f32>(model.position, 1.0);
|
||||||
|
|
||||||
|
var out: VertexOutput;
|
||||||
|
out.clip_position = camera.proj * camera.view * world_position;
|
||||||
|
out.tex_coords = model.tex_coords;
|
||||||
|
out.tangent_position = tangent_matrix * world_position.xyz;
|
||||||
|
out.tangent_light_position = tangent_matrix * light.position;
|
||||||
|
out.tangent_view_position = tangent_matrix * camera.position.xyz;
|
||||||
|
|
||||||
|
out.world_position = world_position;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn fs_main(vert: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
|
return vec4<f32>(0.5, 0.5, 0.5, 0.1);
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ use super::model::Vertex;
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
pub position: cgmath::Vector3<f32>,
|
pub position: cgmath::Vector3<f32>,
|
||||||
pub rotation: cgmath::Quaternion<f32>,
|
pub rotation: cgmath::Quaternion<f32>,
|
||||||
|
pub scale: cgmath::Vector3<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -16,6 +17,7 @@ impl Instance {
|
||||||
pub fn to_raw(&self) -> InstanceRaw {
|
pub fn to_raw(&self) -> InstanceRaw {
|
||||||
InstanceRaw {
|
InstanceRaw {
|
||||||
model: (cgmath::Matrix4::from_translation(self.position)
|
model: (cgmath::Matrix4::from_translation(self.position)
|
||||||
|
* cgmath::Matrix4::from_nonuniform_scale(self.scale.x, self.scale.y, self.scale.z)
|
||||||
* cgmath::Matrix4::from(self.rotation))
|
* cgmath::Matrix4::from(self.rotation))
|
||||||
.into(),
|
.into(),
|
||||||
normal: cgmath::Matrix3::from(self.rotation).into(),
|
normal: cgmath::Matrix3::from(self.rotation).into(),
|
||||||
|
|
|
@ -155,4 +155,63 @@ impl Mesh {
|
||||||
v.bitangent = (cgmath::Vector3::from(v.bitangent) * denom).into();
|
v.bitangent = (cgmath::Vector3::from(v.bitangent) * denom).into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn cube(device: &wgpu::Device, size: [f32; 3], name: &str, material_index: usize) -> Mesh {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let mut vertices = vec![
|
||||||
|
// front
|
||||||
|
ModelVertex { position: [-size[0], -size[1], -size[2]], tex_coords: [0.0, 0.0], normal: [-size[0], -size[1], -size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [ size[0], -size[1], -size[2]], tex_coords: [0.0, 0.0], normal: [ size[0], -size[1], -size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [ size[0], size[1], -size[2]], tex_coords: [0.0, 0.0], normal: [ size[0], size[1], -size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [-size[0], size[1], -size[2]], tex_coords: [0.0, 0.0], normal: [-size[0], size[1], -size[2]], ..Default::default() },
|
||||||
|
|
||||||
|
// back
|
||||||
|
ModelVertex { position: [-size[0], -size[1], size[2]], tex_coords: [0.0, 0.0], normal: [-size[0], -size[1], size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [ size[0], -size[1], size[2]], tex_coords: [0.0, 0.0], normal: [ size[0], -size[1], size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [ size[0], size[1], size[2]], tex_coords: [0.0, 0.0], normal: [ size[0], size[1], size[2]], ..Default::default() },
|
||||||
|
ModelVertex { position: [-size[0], size[1], size[2]], tex_coords: [0.0, 0.0], normal: [-size[0], size[1], size[2]], ..Default::default() },
|
||||||
|
];
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let indices = vec![
|
||||||
|
// front
|
||||||
|
0, 1, 2,
|
||||||
|
2, 3, 0,
|
||||||
|
// back
|
||||||
|
4, 6, 5,
|
||||||
|
4, 7, 6,
|
||||||
|
// left
|
||||||
|
0, 3, 4,
|
||||||
|
3, 7, 4,
|
||||||
|
// right
|
||||||
|
1, 2, 5,
|
||||||
|
2, 6, 5,
|
||||||
|
// top
|
||||||
|
2, 7, 3,
|
||||||
|
2, 6, 7,
|
||||||
|
// bottom
|
||||||
|
1, 4, 0,
|
||||||
|
1, 5, 4
|
||||||
|
];
|
||||||
|
Mesh::calc_tangents(&indices, &mut vertices);
|
||||||
|
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(&format!("{:?} Vertex Buffer", name)),
|
||||||
|
contents: bytemuck::cast_slice(&vertices),
|
||||||
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
|
});
|
||||||
|
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some(&format!("{:?} Index Buffer", name)),
|
||||||
|
contents: bytemuck::cast_slice(&indices),
|
||||||
|
usage: wgpu::BufferUsages::INDEX,
|
||||||
|
});
|
||||||
|
|
||||||
|
Mesh {
|
||||||
|
name: name.to_string(),
|
||||||
|
vertex_buffer,
|
||||||
|
index_buffer,
|
||||||
|
num_elements: indices.len() as u32,
|
||||||
|
material: material_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ impl RenderPass {
|
||||||
vertex_layouts: &[VertexBufferLayout],
|
vertex_layouts: &[VertexBufferLayout],
|
||||||
label: &str,
|
label: &str,
|
||||||
is_shadow: bool,
|
is_shadow: bool,
|
||||||
|
has_transparency: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
label: Some((label.to_owned() + " pipeline Layout").as_str()),
|
label: Some((label.to_owned() + " pipeline Layout").as_str()),
|
||||||
|
@ -38,6 +39,7 @@ impl RenderPass {
|
||||||
shader,
|
shader,
|
||||||
label,
|
label,
|
||||||
is_shadow,
|
is_shadow,
|
||||||
|
has_transparency,
|
||||||
);
|
);
|
||||||
|
|
||||||
Self { pipeline }
|
Self { pipeline }
|
||||||
|
@ -52,14 +54,25 @@ impl RenderPass {
|
||||||
shader: wgpu::ShaderModuleDescriptor,
|
shader: wgpu::ShaderModuleDescriptor,
|
||||||
label: &str,
|
label: &str,
|
||||||
is_shadow: bool,
|
is_shadow: bool,
|
||||||
|
has_transparency: bool,
|
||||||
) -> wgpu::RenderPipeline {
|
) -> wgpu::RenderPipeline {
|
||||||
let shader = device.create_shader_module(shader);
|
let shader = device.create_shader_module(shader);
|
||||||
|
|
||||||
|
let blend_comp = if has_transparency {
|
||||||
|
wgpu::BlendComponent {
|
||||||
|
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||||
|
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||||
|
operation: wgpu::BlendOperation::Add,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wgpu::BlendComponent::REPLACE
|
||||||
|
};
|
||||||
|
|
||||||
let fragment_targets = &[Some(wgpu::ColorTargetState {
|
let fragment_targets = &[Some(wgpu::ColorTargetState {
|
||||||
format: color_format.unwrap_or(wgpu::TextureFormat::Bgra8Unorm),
|
format: color_format.unwrap_or(wgpu::TextureFormat::Bgra8Unorm),
|
||||||
blend: Some(wgpu::BlendState {
|
blend: Some(wgpu::BlendState {
|
||||||
alpha: wgpu::BlendComponent::REPLACE,
|
alpha: blend_comp,
|
||||||
color: wgpu::BlendComponent::REPLACE,
|
color: blend_comp,
|
||||||
}),
|
}),
|
||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})];
|
})];
|
||||||
|
@ -104,8 +117,7 @@ impl RenderPass {
|
||||||
slope_scale: 2.0,
|
slope_scale: 2.0,
|
||||||
clamp: 0.0,
|
clamp: 0.0,
|
||||||
}
|
}
|
||||||
}
|
} else { wgpu::DepthBiasState::default() },
|
||||||
else { wgpu::DepthBiasState::default() },
|
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState {
|
multisample: wgpu::MultisampleState {
|
||||||
count: 1,
|
count: 1,
|
||||||
|
|
|
@ -35,15 +35,19 @@ pub struct State {
|
||||||
queue: wgpu::Queue,
|
queue: wgpu::Queue,
|
||||||
config: wgpu::SurfaceConfiguration,
|
config: wgpu::SurfaceConfiguration,
|
||||||
geometry_pass: RenderPass,
|
geometry_pass: RenderPass,
|
||||||
|
fog_pass: RenderPass,
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
camera_uniform: CameraUniform,
|
camera_uniform: CameraUniform,
|
||||||
camera_buffer: wgpu::Buffer,
|
camera_buffer: wgpu::Buffer,
|
||||||
camera_bind_group: wgpu::BindGroup,
|
camera_bind_group: wgpu::BindGroup,
|
||||||
camera_controller: CameraController,
|
camera_controller: CameraController,
|
||||||
instances: Vec<Instance>,
|
geom_instances: Vec<Instance>,
|
||||||
instance_buffer: wgpu::Buffer,
|
geom_instance_buffer: wgpu::Buffer,
|
||||||
|
fog_instances: Vec<Instance>,
|
||||||
|
fog_instance_buffer: wgpu::Buffer,
|
||||||
depth_texture: Texture,
|
depth_texture: Texture,
|
||||||
model: Model,
|
geom_model: Model,
|
||||||
|
fog_model: Model,
|
||||||
light_model: Model,
|
light_model: Model,
|
||||||
light_uniform: LightUniform,
|
light_uniform: LightUniform,
|
||||||
light_buffer: wgpu::Buffer,
|
light_buffer: wgpu::Buffer,
|
||||||
|
@ -350,7 +354,7 @@ impl State {
|
||||||
label: Some("texture_bind_group_layout"),
|
label: Some("texture_bind_group_layout"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let model = resources::load_model_gltf(
|
let geom_model = resources::load_model_gltf(
|
||||||
"models/Sponza.glb",
|
"models/Sponza.glb",
|
||||||
&device,
|
&device,
|
||||||
&queue,
|
&queue,
|
||||||
|
@ -359,6 +363,15 @@ impl State {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let fog_model = resources::load_model_gltf(
|
||||||
|
"models/Cube.glb",
|
||||||
|
&device,
|
||||||
|
&queue,
|
||||||
|
&texture_bind_group_layout,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let light_model = resources::load_model_gltf(
|
let light_model = resources::load_model_gltf(
|
||||||
"models/Cube.glb",
|
"models/Cube.glb",
|
||||||
&device,
|
&device,
|
||||||
|
@ -368,15 +381,28 @@ impl State {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let instances = vec![Instance {
|
let geom_instances = vec![Instance {
|
||||||
position: [0.0, 0.0, 0.0].into(),
|
// this sponza model isn't quite centered
|
||||||
|
position: [60.0, 0.0, 35.0].into(),
|
||||||
rotation: cgmath::Quaternion::one(),
|
rotation: cgmath::Quaternion::one(),
|
||||||
|
scale: [1.0, 1.0, 1.0].into(),
|
||||||
}];
|
}];
|
||||||
|
let geom_instance_data = geom_instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
|
||||||
|
let geom_instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Geometry Instance Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(&geom_instance_data),
|
||||||
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
|
});
|
||||||
|
|
||||||
let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
|
let fog_instances = vec![Instance {
|
||||||
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
position: [0.0, 20.0, 0.0].into(),
|
||||||
label: Some("Instance Buffer"),
|
rotation: cgmath::Quaternion::one(),
|
||||||
contents: bytemuck::cast_slice(&instance_data),
|
scale: [1360.0, 20.0, 600.0].into(),
|
||||||
|
}];
|
||||||
|
let fog_instance_data = fog_instances.iter().map(Instance::to_raw).collect::<Vec<_>>();
|
||||||
|
let fog_instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Fog Instance Buffer"),
|
||||||
|
contents: bytemuck::cast_slice(&fog_instance_data),
|
||||||
usage: wgpu::BufferUsages::VERTEX,
|
usage: wgpu::BufferUsages::VERTEX,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -393,6 +419,7 @@ impl State {
|
||||||
&[ModelVertex::desc(), InstanceRaw::desc()],
|
&[ModelVertex::desc(), InstanceRaw::desc()],
|
||||||
"light depth pass",
|
"light depth pass",
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let geometry_pass = RenderPass::new(
|
let geometry_pass = RenderPass::new(
|
||||||
|
@ -410,6 +437,25 @@ impl State {
|
||||||
&[ModelVertex::desc(), InstanceRaw::desc()],
|
&[ModelVertex::desc(), InstanceRaw::desc()],
|
||||||
"geometry pass",
|
"geometry pass",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
let fog_pass = RenderPass::new(
|
||||||
|
&device,
|
||||||
|
&[
|
||||||
|
&camera_bind_group_layout,
|
||||||
|
&light_bind_group_layout,
|
||||||
|
&light_depth_bind_group_layout,
|
||||||
|
&texture_bind_group_layout,
|
||||||
|
],
|
||||||
|
&[],
|
||||||
|
"fog.wgsl",
|
||||||
|
Some(config.format),
|
||||||
|
Some(Texture::DEPTH_FORMAT),
|
||||||
|
&[ModelVertex::desc(), InstanceRaw::desc()],
|
||||||
|
"fog pass",
|
||||||
|
false,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
let light_debug_pass = RenderPass::new(
|
let light_debug_pass = RenderPass::new(
|
||||||
|
@ -422,6 +468,7 @@ impl State {
|
||||||
&[ModelVertex::desc()],
|
&[ModelVertex::desc()],
|
||||||
"light debug pass",
|
"light debug pass",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -431,15 +478,19 @@ impl State {
|
||||||
queue,
|
queue,
|
||||||
config,
|
config,
|
||||||
geometry_pass,
|
geometry_pass,
|
||||||
|
fog_pass,
|
||||||
camera,
|
camera,
|
||||||
camera_uniform,
|
camera_uniform,
|
||||||
camera_buffer,
|
camera_buffer,
|
||||||
camera_bind_group,
|
camera_bind_group,
|
||||||
camera_controller,
|
camera_controller,
|
||||||
instances,
|
geom_instances,
|
||||||
instance_buffer,
|
geom_instance_buffer,
|
||||||
|
fog_instances,
|
||||||
|
fog_instance_buffer,
|
||||||
depth_texture,
|
depth_texture,
|
||||||
model,
|
geom_model,
|
||||||
|
fog_model,
|
||||||
light_model,
|
light_model,
|
||||||
light_uniform,
|
light_uniform,
|
||||||
light_buffer,
|
light_buffer,
|
||||||
|
@ -546,11 +597,11 @@ impl State {
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
light_depth_render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
|
light_depth_render_pass.set_vertex_buffer(1, self.geom_instance_buffer.slice(..));
|
||||||
light_depth_render_pass.set_pipeline(&self.light_depth_pass.pipeline);
|
light_depth_render_pass.set_pipeline(&self.light_depth_pass.pipeline);
|
||||||
light_depth_render_pass.draw_model_instanced(
|
light_depth_render_pass.draw_model_instanced(
|
||||||
&self.model,
|
&self.geom_model,
|
||||||
0..self.instances.len() as u32,
|
0..self.geom_instances.len() as u32,
|
||||||
[&self.camera_bind_group, &self.light_bind_group].into(),
|
[&self.camera_bind_group, &self.light_bind_group].into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -598,11 +649,45 @@ impl State {
|
||||||
occlusion_query_set: None,
|
occlusion_query_set: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
geom_render_pass.set_vertex_buffer(1, self.instance_buffer.slice(..));
|
geom_render_pass.set_vertex_buffer(1, self.geom_instance_buffer.slice(..));
|
||||||
geom_render_pass.set_pipeline(&self.geometry_pass.pipeline);
|
geom_render_pass.set_pipeline(&self.geometry_pass.pipeline);
|
||||||
geom_render_pass.draw_model_instanced(
|
geom_render_pass.draw_model_instanced(
|
||||||
&self.model,
|
&self.geom_model,
|
||||||
0..self.instances.len() as u32,
|
0..self.geom_instances.len() as u32,
|
||||||
|
[&self.camera_bind_group, &self.light_bind_group, &self.light_depth_bind_group].into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
encoder.pop_debug_group();
|
||||||
|
|
||||||
|
encoder.push_debug_group("fog pass");
|
||||||
|
{
|
||||||
|
let mut fog_render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: Some("Fog Render Pass"),
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &surface_view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Load,
|
||||||
|
store: StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
|
||||||
|
view: &self.depth_texture.view,
|
||||||
|
depth_ops: Some(wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Load,
|
||||||
|
store: StoreOp::Store,
|
||||||
|
}),
|
||||||
|
stencil_ops: None,
|
||||||
|
}),
|
||||||
|
timestamp_writes: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
fog_render_pass.set_vertex_buffer(1, self.fog_instance_buffer.slice(..));
|
||||||
|
fog_render_pass.set_pipeline(&self.fog_pass.pipeline);
|
||||||
|
fog_render_pass.draw_model_instanced(
|
||||||
|
&self.fog_model,
|
||||||
|
0..self.fog_instances.len() as u32,
|
||||||
[&self.camera_bind_group, &self.light_bind_group, &self.light_depth_bind_group].into(),
|
[&self.camera_bind_group, &self.light_bind_group, &self.light_depth_bind_group].into(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue