thinking about shaders
This commit is contained in:
@@ -36,16 +36,17 @@ float fetch_shadow(int light_id, vec4 homogeneous_coords) {
|
||||
if (homogeneous_coords.w <= 0.0) {
|
||||
return 1.0;
|
||||
}
|
||||
// compensate for the Y-flip difference between the NDC and texture coordinates
|
||||
// compensate for the Y-flip difference between the normalized device
|
||||
// coordinates (NDC) and texture coordinates
|
||||
const vec2 flip_correction = vec2(0.5, -0.5);
|
||||
// compute texture coordinates for shadow lookup
|
||||
vec4 light_local = vec4(
|
||||
// I don't know what kind of jank shit is going on on this line
|
||||
homogeneous_coords.xy * flip_correction/homogeneous_coords.w + 0.5,
|
||||
light_id,
|
||||
homogeneous_coords.z / homogeneous_coords.w
|
||||
light_id, // array layer
|
||||
homogeneous_coords.z / homogeneous_coords.w // D-Ref
|
||||
);
|
||||
// do the lookup, using HW PCF and comparison
|
||||
// do the lookup, using HW percentage closer filtering(PCF) and comparison
|
||||
return texture(sampler2DArrayShadow(t_Shadow, s_Shadow), light_local);
|
||||
}
|
||||
|
||||
|
||||
4
shaders/g_buffer_input.frag
Normal file
4
shaders/g_buffer_input.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 450
|
||||
|
||||
void main() {
|
||||
}
|
||||
20
shaders/g_buffer_input.vert
Normal file
20
shaders/g_buffer_input.vert
Normal file
@@ -0,0 +1,20 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 a_Pos;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) uniform Globals {
|
||||
mat4 u_ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Entity {
|
||||
mat4 u_World;
|
||||
vec4 u_Color;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = u_ViewProj * u_World * vec4(a_Pos);
|
||||
}
|
||||
@@ -65,4 +65,13 @@ pub struct ShadowUniforms {
|
||||
}
|
||||
|
||||
unsafe impl Pod for ShadowUniforms {}
|
||||
unsafe impl Zeroable for ShadowUniforms {}
|
||||
unsafe impl Zeroable for ShadowUniforms {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct CameraProjectionView {
|
||||
proj: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
unsafe impl Pod for CameraProjectionView {}
|
||||
unsafe impl Zeroable for CameraProjectionView {}
|
||||
@@ -33,11 +33,13 @@ use crate::current_ui;
|
||||
use crate::geometry::{load_obj, RawMesh, Vertex};
|
||||
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
||||
use crate::light::{DirectionalLight, LightRaw};
|
||||
use crate::render::{EntityUniforms, ForwardUniforms, ShadowUniforms};
|
||||
use crate::render::{EntityUniforms, ForwardUniforms, ShadowUniforms, CameraProjectionView};
|
||||
|
||||
/// A render pass consists of a pipeline, bindgroup, and uniform buf
|
||||
/// The uniform buf is just the ShadowUniforms or ForwardUniforms
|
||||
/// They are uniform across all cu's.
|
||||
/// And the bindgroup is just the localbindgroup (the EntityUniforms) and the rest
|
||||
///
|
||||
pub struct Pass {
|
||||
pub pipeline: wgpu::RenderPipeline,
|
||||
pub bind_group: wgpu::BindGroup,
|
||||
@@ -45,6 +47,7 @@ pub struct Pass {
|
||||
}
|
||||
|
||||
pub struct RenderState {
|
||||
|
||||
swapchain: SwapChain,
|
||||
swapchain_description: SwapChainDescriptor,
|
||||
instance: Arc<Instance>,
|
||||
@@ -62,6 +65,8 @@ pub struct RenderState {
|
||||
pub(in crate::render) forward_pass: Pass,
|
||||
pub(in crate::render) forward_depth: wgpu::TextureView,
|
||||
|
||||
pub(in crate::render) gbuffer_pass: Pass,
|
||||
|
||||
entity_bind_group_layout: BindGroupLayout,
|
||||
|
||||
pub(in crate::render) light_uniform_buf: wgpu::Buffer,
|
||||
@@ -302,6 +307,107 @@ impl RenderState {
|
||||
hands-off global lighting / point lights
|
||||
*/
|
||||
|
||||
// This pass is just going to forward the vertex info to the fragments
|
||||
// And they are going to render to the gbuffer
|
||||
let g_buffer_pass = {
|
||||
let uniform_size = mem::size_of::<CameraProjectionView>() as wgpu::BufferAddress;
|
||||
|
||||
// Pretty sure this is the camera projction
|
||||
let bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("g-buffer input pass bindgroup layout (cam)"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0, // global
|
||||
visibility: wgpu::ShaderStage::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
min_binding_size: wgpu::BufferSize::new(uniform_size),
|
||||
has_dynamic_offset: false,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
|
||||
// Pipeline is similar between passes, but with a different label
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("g-buffer input pipeline layout"),
|
||||
bind_group_layouts: &[&bind_group_layout, &entity_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
// Holds the shadow uniforms, which is just a 4 vec of quaternians
|
||||
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("shadow pass shadow uniform buffer"),
|
||||
size: uniform_size,
|
||||
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||
mapped_at_creation: false,
|
||||
});
|
||||
|
||||
// Create bind group
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: Some("Shadow uniform bind group"),
|
||||
layout: &bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &uniform_buf,
|
||||
offset: 0,
|
||||
size: wgpu::BufferSize::new(uniform_size),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
});
|
||||
|
||||
// Create the render pipeline
|
||||
let vs_module =
|
||||
device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.vert.spv"));
|
||||
let fs_module =
|
||||
device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.frag.spv"));
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("shadow"),
|
||||
layout: Some(&pipeline_layout),
|
||||
|
||||
vertex: VertexState {
|
||||
module: &vs_module,
|
||||
entry_point: "main",
|
||||
buffers: &[vb_desc.clone()],
|
||||
},
|
||||
fragment: Some(FragmentState {
|
||||
module: &fs_module,
|
||||
entry_point: "main",
|
||||
targets: &[],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: wgpu::CullMode::Back,
|
||||
..Default::default()
|
||||
},
|
||||
depth_stencil: Some(wgpu::DepthStencilState {
|
||||
format: Self::SHADOW_FORMAT,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||
stencil: wgpu::StencilState::default(),
|
||||
bias: wgpu::DepthBiasState {
|
||||
constant: 2, // corresponds to bilinear filtering
|
||||
slope_scale: 2.0,
|
||||
clamp: 0.0,
|
||||
},
|
||||
clamp_depth: device.features().contains(wgpu::Features::DEPTH_CLAMPING),
|
||||
}),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
});
|
||||
|
||||
Pass {
|
||||
pipeline,
|
||||
bind_group,
|
||||
uniform_buf,
|
||||
}
|
||||
};
|
||||
|
||||
let shadow_pass = {
|
||||
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
||||
|
||||
@@ -356,14 +462,6 @@ impl RenderState {
|
||||
size: wgpu::BufferSize::new(uniform_size),
|
||||
},
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Buffer {
|
||||
buffer: &g_buffer,
|
||||
offset: 0,
|
||||
size: wgpu::BufferSize::new(uniform_size),
|
||||
},
|
||||
},
|
||||
],
|
||||
label: Some("Shadow uniform bind group"),
|
||||
});
|
||||
@@ -655,6 +753,7 @@ impl RenderState {
|
||||
shadow_pass,
|
||||
forward_pass,
|
||||
forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()),
|
||||
gbuffer_pass: g_buffer_pass,
|
||||
entity_bind_group_layout: entity_bind_group_layout,
|
||||
shadow_target_views: shadow_target_views,
|
||||
light_uniform_buf,
|
||||
|
||||
@@ -36,9 +36,7 @@ use crate::geometry::{load_obj, Vertex};
|
||||
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
||||
use crate::light::{DirectionalLight, LightRaw};
|
||||
use crate::render::state::RenderState;
|
||||
use crate::render::{
|
||||
insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms,
|
||||
};
|
||||
use crate::render::{insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms, ForwardUniforms};
|
||||
|
||||
#[system]
|
||||
#[write_component(Camera)]
|
||||
@@ -235,6 +233,7 @@ pub fn render_test(
|
||||
mesh_stack.push(mesh.clone());
|
||||
}
|
||||
|
||||
// Update the light uniforms only if flagged
|
||||
if renderer.lights_are_dirty {
|
||||
renderer.lights_are_dirty = false;
|
||||
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
|
||||
@@ -247,6 +246,39 @@ pub fn render_test(
|
||||
}
|
||||
}
|
||||
|
||||
// Render the g buffer
|
||||
push_debug_group_checked("g-buffer stuff", &mut encoder);
|
||||
{
|
||||
|
||||
|
||||
insert_debug_marker_checked("render entities", &mut encoder);
|
||||
|
||||
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("render pass"),
|
||||
color_attachments: &[],
|
||||
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: &light.target_view,
|
||||
depth_ops: Some(wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(1.0),
|
||||
store: true,
|
||||
}),
|
||||
stencil_ops: None,
|
||||
}),
|
||||
});
|
||||
pass.set_pipeline(&renderer.shadow_pass.pipeline);
|
||||
pass.set_bind_group(0, &renderer.shadow_pass.bind_group, &[]);
|
||||
|
||||
for mesh in &mesh_stack {
|
||||
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
||||
// TODO, pipe through this index format through the mesh
|
||||
pass.set_index_buffer(mesh.index_buffer.slice(..), mesh.index_format);
|
||||
pass.set_vertex_buffer(0, mesh.vertex_buffer.slice(..));
|
||||
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
pop_debug_group_checked(&mut encoder);
|
||||
|
||||
push_debug_group_checked("shadow passes", &mut encoder);
|
||||
|
||||
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
|
||||
@@ -327,6 +359,7 @@ pub fn render_test(
|
||||
|
||||
let mut query = <(&mut Position, &mut Mesh)>::query();
|
||||
|
||||
// I could use that mesh stack here lol
|
||||
for (pos, mesh) in query.iter_mut(world) {
|
||||
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
||||
// TODO: Pipe this in through the mesh
|
||||
@@ -335,9 +368,11 @@ pub fn render_test(
|
||||
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
pop_debug_group_checked(&mut encoder);
|
||||
pop_debug_group_checked(&mut encoder);
|
||||
|
||||
// Run the Imgui render
|
||||
{
|
||||
let mut imgui_context = &mut imgui_context.lock().unwrap().context;
|
||||
let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform;
|
||||
|
||||
Reference in New Issue
Block a user