Compare commits
No commits in common. "fd65f754cfb4958a40a6de8f60055d7f0f058d13" and "7b2d2424a36d97ec6710a1640e89f3aeca9f330f" have entirely different histories.
fd65f754cf
...
7b2d2424a3
|
@ -139,17 +139,16 @@ fn setup_scene_plugin(game: &mut Game) {
|
||||||
world.spawn((
|
world.spawn((
|
||||||
platform_mesh.clone(),
|
platform_mesh.clone(),
|
||||||
WorldTransform::default(),
|
WorldTransform::default(),
|
||||||
//Transform::from_xyz(0.0, -5.0, -5.0),
|
Transform::from_xyz(0.0, -5.0, -5.0),
|
||||||
Transform::new(math::vec3(0.0, -5.0, -5.0), math::Quat::IDENTITY, math::vec3(5.0, 1.0, 5.0)),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut light_tran = Transform::from_xyz(0.0, 2.5, 0.0);
|
let mut light_tran = Transform::from_xyz(-5.5, 2.5, -3.0);
|
||||||
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
light_tran.scale = Vec3::new(0.5, 0.5, 0.5);
|
||||||
light_tran.rotate_x(math::Angle::Degrees(-45.0));
|
light_tran.rotate_x(math::Angle::Degrees(-45.0));
|
||||||
light_tran.rotate_y(math::Angle::Degrees(-35.0));
|
light_tran.rotate_y(math::Angle::Degrees(-35.0));
|
||||||
world.spawn((
|
world.spawn((
|
||||||
//cube_mesh.clone(),
|
cube_mesh.clone(),
|
||||||
DirectionalLight {
|
DirectionalLight {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
color: Vec3::new(1.0, 0.95, 0.9),
|
color: Vec3::new(1.0, 0.95, 0.9),
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::render::{
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
BasePassSlots, LightBasePassSlots, LightCullComputePassSlots, MeshBufferStorage, RenderAssets,
|
BasePassSlots, LightBasePassSlots, LightCullComputePassSlots, MeshBufferStorage, RenderAssets,
|
||||||
RenderMeshes, ShadowMapsPassSlots,
|
RenderMeshes,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||||
|
@ -26,12 +26,6 @@ pub enum MeshesPassSlots {
|
||||||
Material,
|
Material,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores the bind group and bind group layout for the shadow atlas texture
|
|
||||||
struct ShadowsAtlasBgPair {
|
|
||||||
layout: Arc<wgpu::BindGroupLayout>,
|
|
||||||
bg: Arc<wgpu::BindGroup>,
|
|
||||||
}
|
|
||||||
|
|
||||||
//#[derive(Default)]
|
//#[derive(Default)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct MeshPass {
|
pub struct MeshPass {
|
||||||
|
@ -39,14 +33,11 @@ pub struct MeshPass {
|
||||||
|
|
||||||
pipeline: Option<RenderPipeline>,
|
pipeline: Option<RenderPipeline>,
|
||||||
material_bgl: Arc<wgpu::BindGroupLayout>,
|
material_bgl: Arc<wgpu::BindGroupLayout>,
|
||||||
|
transform_buffers: Option<ResourceData>,
|
||||||
// TODO: find a better way to extract these resources from the main world to be used in the
|
// TODO: find a better way to extract these resources from the main world to be used in the
|
||||||
// render stage.
|
// render stage.
|
||||||
transform_buffers: Option<ResourceData>,
|
|
||||||
render_meshes: Option<ResourceData>,
|
render_meshes: Option<ResourceData>,
|
||||||
mesh_buffers: Option<ResourceData>,
|
mesh_buffers: Option<ResourceData>,
|
||||||
|
|
||||||
shadows_atlas: Option<ShadowsAtlasBgPair>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshPass {
|
impl MeshPass {
|
||||||
|
@ -55,32 +46,38 @@ impl MeshPass {
|
||||||
default_texture: None,
|
default_texture: None,
|
||||||
pipeline: None,
|
pipeline: None,
|
||||||
material_bgl,
|
material_bgl,
|
||||||
|
|
||||||
transform_buffers: None,
|
transform_buffers: None,
|
||||||
render_meshes: None,
|
render_meshes: None,
|
||||||
mesh_buffers: None,
|
mesh_buffers: None,
|
||||||
|
|
||||||
shadows_atlas: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transform_buffers(&self) -> AtomicRef<TransformBuffers> {
|
fn transform_buffers(&self) -> AtomicRef<TransformBuffers> {
|
||||||
self.transform_buffers.as_ref().unwrap().get()
|
self.transform_buffers
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_meshes(&self) -> AtomicRef<RenderMeshes> {
|
fn render_meshes(&self) -> AtomicRef<RenderMeshes> {
|
||||||
self.render_meshes.as_ref().unwrap().get()
|
self.render_meshes
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mesh_buffers(&self) -> AtomicRef<RenderAssets<MeshBufferStorage>> {
|
fn mesh_buffers(&self) -> AtomicRef<RenderAssets<MeshBufferStorage>> {
|
||||||
self.mesh_buffers.as_ref().unwrap().get()
|
self.mesh_buffers
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for MeshPass {
|
impl Node for MeshPass {
|
||||||
fn desc(
|
fn desc(
|
||||||
&mut self,
|
&mut self,
|
||||||
graph: &mut crate::render::graph::RenderGraph,
|
_: &mut crate::render::graph::RenderGraph,
|
||||||
) -> crate::render::graph::NodeDesc {
|
) -> crate::render::graph::NodeDesc {
|
||||||
// load the default texture
|
// load the default texture
|
||||||
//let bytes = include_bytes!("../../default_texture.png");
|
//let bytes = include_bytes!("../../default_texture.png");
|
||||||
|
@ -106,93 +103,17 @@ impl Node for MeshPass {
|
||||||
let device = graph.device();
|
let device = graph.device();
|
||||||
let surface_config_format = graph.view_target().format();
|
let surface_config_format = graph.view_target().format();
|
||||||
|
|
||||||
let atlas_view = graph
|
|
||||||
.slot_value(ShadowMapsPassSlots::ShadowAtlasTextureView)
|
|
||||||
.expect("missing ShadowMapsPassSlots::ShadowAtlasTextureView")
|
|
||||||
.as_texture_view()
|
|
||||||
.unwrap();
|
|
||||||
let atlas_sampler = graph
|
|
||||||
.slot_value(ShadowMapsPassSlots::ShadowAtlasSampler)
|
|
||||||
.expect("missing ShadowMapsPassSlots::ShadowAtlasSampler")
|
|
||||||
.as_sampler()
|
|
||||||
.unwrap();
|
|
||||||
let dir_light_projection_buf = graph
|
|
||||||
.slot_value(ShadowMapsPassSlots::DirLightProjectionBuffer)
|
|
||||||
.expect("missing ShadowMapsPassSlots::DirLightProjectionBuffer")
|
|
||||||
.as_buffer()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let atlas_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
|
||||||
label: Some("bgl_shadows_atlas"),
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 0,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Texture {
|
|
||||||
sample_type: wgpu::TextureSampleType::Depth,
|
|
||||||
view_dimension: wgpu::TextureViewDimension::D2,
|
|
||||||
multisampled: false,
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 1,
|
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
wgpu::BindGroupLayoutEntry {
|
|
||||||
binding: 2,
|
|
||||||
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
|
||||||
ty: wgpu::BindingType::Buffer {
|
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
|
||||||
has_dynamic_offset: false,
|
|
||||||
min_binding_size: None,
|
|
||||||
},
|
|
||||||
count: None,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
let atlas_bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
|
||||||
label: Some("bg_shadows_atlas"),
|
|
||||||
layout: &atlas_layout,
|
|
||||||
entries: &[
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 0,
|
|
||||||
resource: wgpu::BindingResource::TextureView(atlas_view),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 1,
|
|
||||||
resource: wgpu::BindingResource::Sampler(atlas_sampler),
|
|
||||||
},
|
|
||||||
wgpu::BindGroupEntry {
|
|
||||||
binding: 2,
|
|
||||||
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
|
||||||
buffer: dir_light_projection_buf,
|
|
||||||
offset: 0,
|
|
||||||
size: None,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
self.shadows_atlas = Some(ShadowsAtlasBgPair {
|
|
||||||
layout: Arc::new(atlas_layout),
|
|
||||||
bg: Arc::new(atlas_bg),
|
|
||||||
});
|
|
||||||
|
|
||||||
let camera_bgl = graph.bind_group_layout(BasePassSlots::Camera);
|
let camera_bgl = graph.bind_group_layout(BasePassSlots::Camera);
|
||||||
let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights);
|
let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights);
|
||||||
let light_grid_bgl =
|
let light_grid_bgl =
|
||||||
graph.bind_group_layout(LightCullComputePassSlots::LightIndicesGridGroup);
|
graph.bind_group_layout(LightCullComputePassSlots::LightIndicesGridGroup);
|
||||||
let atlas_bgl = self.shadows_atlas.as_ref().unwrap().layout.clone();
|
|
||||||
|
|
||||||
let shader = Rc::new(Shader {
|
let shader = Rc::new(Shader {
|
||||||
label: Some("base_shader".into()),
|
label: Some("base_shader".into()),
|
||||||
source: include_str!("../../shaders/base.wgsl").to_string(),
|
source: include_str!("../../shaders/base.wgsl").to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
let transforms = world
|
let transforms = world
|
||||||
.try_get_resource_data::<TransformBuffers>()
|
.try_get_resource_data::<TransformBuffers>()
|
||||||
.expect("Missing transform buffers");
|
.expect("Missing transform buffers");
|
||||||
|
@ -208,6 +129,7 @@ impl Node for MeshPass {
|
||||||
.expect("Missing render meshes");
|
.expect("Missing render meshes");
|
||||||
self.mesh_buffers = Some(mesh_buffers.clone());
|
self.mesh_buffers = Some(mesh_buffers.clone());
|
||||||
|
|
||||||
|
|
||||||
let transforms = transforms.get::<TransformBuffers>();
|
let transforms = transforms.get::<TransformBuffers>();
|
||||||
|
|
||||||
self.pipeline = Some(RenderPipeline::create(
|
self.pipeline = Some(RenderPipeline::create(
|
||||||
|
@ -220,7 +142,6 @@ impl Node for MeshPass {
|
||||||
camera_bgl.clone(),
|
camera_bgl.clone(),
|
||||||
lights_bgl.clone(),
|
lights_bgl.clone(),
|
||||||
light_grid_bgl.clone(),
|
light_grid_bgl.clone(),
|
||||||
atlas_bgl,
|
|
||||||
],
|
],
|
||||||
push_constant_ranges: vec![],
|
push_constant_ranges: vec![],
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
|
@ -281,8 +202,6 @@ impl Node for MeshPass {
|
||||||
|
|
||||||
let light_grid_bg = graph.bind_group(LightCullComputePassSlots::LightIndicesGridGroup);
|
let light_grid_bg = graph.bind_group(LightCullComputePassSlots::LightIndicesGridGroup);
|
||||||
|
|
||||||
let shadows_atlas_bg = &self.shadows_atlas.as_ref().unwrap().bg;
|
|
||||||
|
|
||||||
//let material_bg = graph.bind_group(MeshesPassSlots::Material);
|
//let material_bg = graph.bind_group(MeshesPassSlots::Material);
|
||||||
|
|
||||||
/* let pipeline = graph.pipeline(context.label.clone())
|
/* let pipeline = graph.pipeline(context.label.clone())
|
||||||
|
@ -365,8 +284,6 @@ impl Node for MeshPass {
|
||||||
|
|
||||||
pass.set_bind_group(4, light_grid_bg, &[]);
|
pass.set_bind_group(4, light_grid_bg, &[]);
|
||||||
|
|
||||||
pass.set_bind_group(5, shadows_atlas_bg, &[]);
|
|
||||||
|
|
||||||
// if this mesh uses indices, use them to draw the mesh
|
// if this mesh uses indices, use them to draw the mesh
|
||||||
if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() {
|
if let Some((idx_type, indices)) = buffers.buffer_indices.as_ref() {
|
||||||
let indices_len = indices.count() as u32;
|
let indices_len = indices.count() as u32;
|
||||||
|
|
|
@ -27,14 +27,13 @@ pub enum ShadowMapsPassSlots {
|
||||||
ShadowAtlasTexture,
|
ShadowAtlasTexture,
|
||||||
ShadowAtlasTextureView,
|
ShadowAtlasTextureView,
|
||||||
ShadowAtlasSampler,
|
ShadowAtlasSampler,
|
||||||
DirLightProjectionBuffer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||||
pub struct ShadowMapsPassLabel;
|
pub struct ShadowMapsPassLabel;
|
||||||
|
|
||||||
struct LightDepthMap {
|
struct LightDepthMap {
|
||||||
light_projection_buffer: Arc<wgpu::Buffer>,
|
light_projection_buffer: wgpu::Buffer,
|
||||||
bindgroup: wgpu::BindGroup,
|
bindgroup: wgpu::BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,9 +99,9 @@ impl ShadowMapsPass {
|
||||||
|
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||||
label: Some("sampler_shadow_map_atlas"),
|
label: Some("sampler_shadow_map_atlas"),
|
||||||
address_mode_u: wgpu::AddressMode::ClampToBorder,
|
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||||
address_mode_v: wgpu::AddressMode::ClampToBorder,
|
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||||
address_mode_w: wgpu::AddressMode::ClampToBorder,
|
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||||
mag_filter: wgpu::FilterMode::Linear,
|
mag_filter: wgpu::FilterMode::Linear,
|
||||||
min_filter: wgpu::FilterMode::Linear,
|
min_filter: wgpu::FilterMode::Linear,
|
||||||
mipmap_filter: wgpu::FilterMode::Linear,
|
mipmap_filter: wgpu::FilterMode::Linear,
|
||||||
|
@ -126,15 +125,15 @@ impl ShadowMapsPass {
|
||||||
|
|
||||||
fn create_depth_map(&mut self, device: &wgpu::Device, entity: Entity, light_pos: Transform) {
|
fn create_depth_map(&mut self, device: &wgpu::Device, entity: Entity, light_pos: Transform) {
|
||||||
const NEAR_PLANE: f32 = 0.1;
|
const NEAR_PLANE: f32 = 0.1;
|
||||||
const FAR_PLANE: f32 = 25.5;
|
const FAR_PLANE: f32 = 80.0;
|
||||||
|
|
||||||
let ortho_proj =
|
let ortho_proj =
|
||||||
glam::Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, NEAR_PLANE, FAR_PLANE);
|
glam::Mat4::orthographic_rh_gl(-20.0, 20.0, -20.0, 20.0, NEAR_PLANE, FAR_PLANE);
|
||||||
|
|
||||||
let look_view =
|
let look_view =
|
||||||
glam::Mat4::look_to_rh(light_pos.translation, light_pos.forward(), light_pos.up());
|
glam::Mat4::look_to_rh(light_pos.translation, light_pos.forward(), light_pos.up());
|
||||||
|
|
||||||
let light_proj = ortho_proj * look_view;
|
let light_proj = OPENGL_TO_WGPU_MATRIX * (ortho_proj * look_view);
|
||||||
|
|
||||||
let light_projection_buffer =
|
let light_projection_buffer =
|
||||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
|
@ -159,7 +158,7 @@ impl ShadowMapsPass {
|
||||||
self.depth_maps.insert(
|
self.depth_maps.insert(
|
||||||
entity,
|
entity,
|
||||||
LightDepthMap {
|
LightDepthMap {
|
||||||
light_projection_buffer: Arc::new(light_projection_buffer),
|
light_projection_buffer,
|
||||||
bindgroup: bg,
|
bindgroup: bg,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -203,12 +202,6 @@ impl Node for ShadowMapsPass {
|
||||||
Some(SlotValue::Sampler(self.atlas_sampler.clone())),
|
Some(SlotValue::Sampler(self.atlas_sampler.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
node.add_sampler_slot(
|
|
||||||
ShadowMapsPassSlots::DirLightProjectionBuffer,
|
|
||||||
SlotAttribute::Output,
|
|
||||||
Some(SlotValue::Lazy),
|
|
||||||
);
|
|
||||||
|
|
||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,12 +222,6 @@ impl Node for ShadowMapsPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the light projection buffer slot
|
|
||||||
let (_, dir_depth_map) = self.depth_maps.iter().next().unwrap();
|
|
||||||
let val = graph.slot_value_mut(ShadowMapsPassSlots::DirLightProjectionBuffer)
|
|
||||||
.unwrap();
|
|
||||||
*val = SlotValue::Buffer(dir_depth_map.light_projection_buffer.clone());
|
|
||||||
|
|
||||||
if self.pipeline.is_none() {
|
if self.pipeline.is_none() {
|
||||||
let shader = Rc::new(Shader {
|
let shader = Rc::new(Shader {
|
||||||
label: Some("shader_shadows".into()),
|
label: Some("shader_shadows".into()),
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl BasicRenderer {
|
||||||
|
|
||||||
let (device, queue) = adapter.request_device(
|
let (device, queue) = adapter.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES | wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
|
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
|
||||||
// WebGL does not support all wgpu features.
|
// WebGL does not support all wgpu features.
|
||||||
// Not sure if the engine will ever completely support WASM,
|
// Not sure if the engine will ever completely support WASM,
|
||||||
// but its here just in case
|
// but its here just in case
|
||||||
|
@ -147,16 +147,14 @@ impl BasicRenderer {
|
||||||
forward_plus_graph.add_node(LightCullComputePassLabel, LightCullComputePass::new(size));
|
forward_plus_graph.add_node(LightCullComputePassLabel, LightCullComputePass::new(size));
|
||||||
|
|
||||||
debug!("Adding mesh pass");
|
debug!("Adding mesh pass");
|
||||||
forward_plus_graph.add_node(ShadowMapsPassLabel, ShadowMapsPass::new(&device));
|
|
||||||
|
|
||||||
let mesh_prep = MeshPrepNode::new(&device);
|
let mesh_prep = MeshPrepNode::new(&device);
|
||||||
let material_bgl = mesh_prep.material_bgl.clone();
|
let material_bgl = mesh_prep.material_bgl.clone();
|
||||||
forward_plus_graph.add_node(MeshPrepNodeLabel, mesh_prep);
|
forward_plus_graph.add_node(MeshPrepNodeLabel, mesh_prep);
|
||||||
forward_plus_graph.add_node(MeshesPassLabel, MeshPass::new(material_bgl));
|
forward_plus_graph.add_node(MeshesPassLabel, MeshPass::new(material_bgl));
|
||||||
|
|
||||||
|
forward_plus_graph.add_node(ShadowMapsPassLabel, ShadowMapsPass::new(&device));
|
||||||
|
|
||||||
forward_plus_graph.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
forward_plus_graph.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
||||||
forward_plus_graph.add_edge(LightCullComputePassLabel, MeshesPassLabel);
|
|
||||||
forward_plus_graph.add_edge(MeshPrepNodeLabel, MeshesPassLabel);
|
forward_plus_graph.add_edge(MeshPrepNodeLabel, MeshesPassLabel);
|
||||||
|
|
||||||
// run ShadowMapsPass after MeshPrep and before MeshesPass
|
// run ShadowMapsPass after MeshPrep and before MeshesPass
|
||||||
|
|
|
@ -19,7 +19,6 @@ struct VertexOutput {
|
||||||
@location(0) tex_coords: vec2<f32>,
|
@location(0) tex_coords: vec2<f32>,
|
||||||
@location(1) world_position: vec3<f32>,
|
@location(1) world_position: vec3<f32>,
|
||||||
@location(2) world_normal: vec3<f32>,
|
@location(2) world_normal: vec3<f32>,
|
||||||
@location(3) frag_pos_light_space: vec4<f32>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TransformData {
|
struct TransformData {
|
||||||
|
@ -71,18 +70,16 @@ fn vs_main(
|
||||||
) -> VertexOutput {
|
) -> VertexOutput {
|
||||||
var out: VertexOutput;
|
var out: VertexOutput;
|
||||||
|
|
||||||
var world_position: vec4<f32> = u_model_transform_data.transform * vec4<f32>(model.position, 1.0);
|
|
||||||
out.world_position = world_position.xyz;
|
|
||||||
|
|
||||||
out.tex_coords = model.tex_coords;
|
out.tex_coords = model.tex_coords;
|
||||||
out.clip_position = u_camera.view_projection * world_position;
|
out.clip_position = u_camera.view_projection * u_model_transform_data.transform * vec4<f32>(model.position, 1.0);
|
||||||
|
|
||||||
// the normal mat is actually only a mat3x3, but there's a bug in wgpu: https://github.com/gfx-rs/wgpu-rs/issues/36
|
// the normal mat is actually only a mat3x3, but there's a bug in wgpu: https://github.com/gfx-rs/wgpu-rs/issues/36
|
||||||
let normal_mat4 = u_model_transform_data.normal_matrix;
|
let normal_mat4 = u_model_transform_data.normal_matrix;
|
||||||
let normal_mat = mat3x3(normal_mat4[0].xyz, normal_mat4[1].xyz, normal_mat4[2].xyz);
|
let normal_mat = mat3x3(normal_mat4[0].xyz, normal_mat4[1].xyz, normal_mat4[2].xyz);
|
||||||
out.world_normal = normalize(normal_mat * model.normal, );
|
out.world_normal = normalize(normal_mat * model.normal, );
|
||||||
|
|
||||||
out.frag_pos_light_space = u_light_space_matrix * world_position;
|
var world_position: vec4<f32> = u_model_transform_data.transform * vec4<f32>(model.position, 1.0);
|
||||||
|
out.world_position = world_position.xyz;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -117,13 +114,6 @@ var<storage, read_write> u_light_indices: array<u32>;
|
||||||
@group(4) @binding(1)
|
@group(4) @binding(1)
|
||||||
var t_light_grid: texture_storage_2d<rg32uint, read_write>; // vec2<u32>
|
var t_light_grid: texture_storage_2d<rg32uint, read_write>; // vec2<u32>
|
||||||
|
|
||||||
@group(5) @binding(0)
|
|
||||||
var t_shadow_maps_atlas: texture_depth_2d;
|
|
||||||
@group(5) @binding(1)
|
|
||||||
var s_shadow_maps_atlas: sampler;
|
|
||||||
@group(5) @binding(2)
|
|
||||||
var<uniform> u_light_space_matrix: mat4x4<f32>;
|
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
if (u_camera.tile_debug == 1u) {
|
if (u_camera.tile_debug == 1u) {
|
||||||
|
@ -149,27 +139,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let light: Light = u_lights.data[light_index];
|
let light: Light = u_lights.data[light_index];
|
||||||
|
|
||||||
if (light.light_ty == LIGHT_TY_DIRECTIONAL) {
|
if (light.light_ty == LIGHT_TY_DIRECTIONAL) {
|
||||||
/*let shadow = calc_shadow(in.frag_pos_light_space);
|
light_res += blinn_phong_dir_light(in.world_position, in.world_normal, light, u_material, specular_color);
|
||||||
return vec4<f32>(vec3<f32>(shadow), 1.0);*/
|
|
||||||
|
|
||||||
/*var proj_coords = in.frag_pos_light_space / in.frag_pos_light_space.w;
|
|
||||||
proj_coords = proj_coords * 0.5 + 0.5;
|
|
||||||
|
|
||||||
let closest_depth = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, proj_coords.xy, 0.0);
|
|
||||||
let current_depth = proj_coords.z;
|
|
||||||
|
|
||||||
if current_depth > closest_depth {
|
|
||||||
return vec4<f32>(vec3<f32>(current_depth), 1.0);
|
|
||||||
} else {
|
|
||||||
return vec4<f32>(vec3<f32>(closest_depth), 1.0);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//return vec4<f32>(vec3<f32>(closest_depth), 1.0);
|
|
||||||
//let shadow = select(0.0, 1.0, current_depth > closest_depth);
|
|
||||||
let light_dir = normalize(-light.direction);
|
|
||||||
|
|
||||||
let shadow = calc_shadow(in.world_normal, light_dir, in.frag_pos_light_space);
|
|
||||||
light_res += blinn_phong_dir_light(in.world_position, in.world_normal, light, u_material, specular_color, shadow);
|
|
||||||
} else if (light.light_ty == LIGHT_TY_POINT) {
|
} else if (light.light_ty == LIGHT_TY_POINT) {
|
||||||
light_res += blinn_phong_point_light(in.world_position, in.world_normal, light, u_material, specular_color);
|
light_res += blinn_phong_point_light(in.world_position, in.world_normal, light, u_material, specular_color);
|
||||||
} else if (light.light_ty == LIGHT_TY_SPOT) {
|
} else if (light.light_ty == LIGHT_TY_SPOT) {
|
||||||
|
@ -181,34 +151,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
return vec4<f32>(light_object_res, object_color.a);
|
return vec4<f32>(light_object_res, object_color.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_shadow(normal: vec3<f32>, light_dir: vec3<f32>, frag_pos_light_space: vec4<f32>) -> f32 {
|
|
||||||
var proj_coords = frag_pos_light_space.xyz / frag_pos_light_space.w;
|
|
||||||
// for some reason the y component is clipped after transforming
|
|
||||||
proj_coords.y = -proj_coords.y;
|
|
||||||
|
|
||||||
// Remap xy to [0.0, 1.0]
|
|
||||||
let xy_remapped = proj_coords.xy * 0.5 + 0.5;
|
|
||||||
proj_coords.x = xy_remapped.x;
|
|
||||||
proj_coords.y = xy_remapped.y;
|
|
||||||
|
|
||||||
let closest_depth = textureSampleLevel(t_shadow_maps_atlas, s_shadow_maps_atlas, proj_coords.xy, 0.0);
|
|
||||||
let current_depth = proj_coords.z;
|
|
||||||
|
|
||||||
// use a bias to avoid shadow acne
|
|
||||||
let bias = max(0.05 * (1.0 - dot(normal, light_dir)), 0.005);
|
|
||||||
var shadow = 0.0;
|
|
||||||
if current_depth - bias > closest_depth {
|
|
||||||
shadow = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dont cast shadows outside the light's far plane
|
|
||||||
if (proj_coords.z > 1.0) {
|
|
||||||
shadow = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
||||||
let tile_index_float: vec2<f32> = in.clip_position.xy / 16.0;
|
let tile_index_float: vec2<f32> = in.clip_position.xy / 16.0;
|
||||||
let tile_index = vec2<u32>(floor(tile_index_float));
|
let tile_index = vec2<u32>(floor(tile_index_float));
|
||||||
|
@ -224,7 +166,7 @@ fn debug_grid(in: VertexOutput) -> vec4<f32> {
|
||||||
return vec4<f32>(ratio, ratio, ratio, 1.0);
|
return vec4<f32>(ratio, ratio, ratio, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blinn_phong_dir_light(world_pos: vec3<f32>, world_norm: vec3<f32>, dir_light: Light, material: Material, specular_factor: vec3<f32>, shadow: f32) -> vec3<f32> {
|
fn blinn_phong_dir_light(world_pos: vec3<f32>, world_norm: vec3<f32>, dir_light: Light, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||||
let light_color = dir_light.color.xyz;
|
let light_color = dir_light.color.xyz;
|
||||||
let camera_view_pos = u_camera.position;
|
let camera_view_pos = u_camera.position;
|
||||||
|
|
||||||
|
@ -250,7 +192,7 @@ fn blinn_phong_dir_light(world_pos: vec3<f32>, world_norm: vec3<f32>, dir_light:
|
||||||
diffuse_color *= dir_light.diffuse;
|
diffuse_color *= dir_light.diffuse;
|
||||||
specular_color *= dir_light.specular;*/
|
specular_color *= dir_light.specular;*/
|
||||||
|
|
||||||
return (ambient_color + (1.0 - shadow) * (diffuse_color + specular_color)) * dir_light.intensity;
|
return (ambient_color + diffuse_color + specular_color) * dir_light.intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_light: Light, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
fn blinn_phong_point_light(world_pos: vec3<f32>, world_norm: vec3<f32>, point_light: Light, material: Material, specular_factor: vec3<f32>) -> vec3<f32> {
|
||||||
|
|
Loading…
Reference in New Issue