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) {
|
if (homogeneous_coords.w <= 0.0) {
|
||||||
return 1.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);
|
const vec2 flip_correction = vec2(0.5, -0.5);
|
||||||
// compute texture coordinates for shadow lookup
|
// compute texture coordinates for shadow lookup
|
||||||
vec4 light_local = vec4(
|
vec4 light_local = vec4(
|
||||||
// I don't know what kind of jank shit is going on on this line
|
// 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,
|
homogeneous_coords.xy * flip_correction/homogeneous_coords.w + 0.5,
|
||||||
light_id,
|
light_id, // array layer
|
||||||
homogeneous_coords.z / homogeneous_coords.w
|
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);
|
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);
|
||||||
|
}
|
||||||
@@ -66,3 +66,12 @@ pub struct ShadowUniforms {
|
|||||||
|
|
||||||
unsafe impl Pod for 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::geometry::{load_obj, RawMesh, Vertex};
|
||||||
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
||||||
use crate::light::{DirectionalLight, LightRaw};
|
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
|
/// A render pass consists of a pipeline, bindgroup, and uniform buf
|
||||||
/// The uniform buf is just the ShadowUniforms or ForwardUniforms
|
/// 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
|
/// And the bindgroup is just the localbindgroup (the EntityUniforms) and the rest
|
||||||
|
///
|
||||||
pub struct Pass {
|
pub struct Pass {
|
||||||
pub pipeline: wgpu::RenderPipeline,
|
pub pipeline: wgpu::RenderPipeline,
|
||||||
pub bind_group: wgpu::BindGroup,
|
pub bind_group: wgpu::BindGroup,
|
||||||
@@ -45,6 +47,7 @@ pub struct Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct RenderState {
|
pub struct RenderState {
|
||||||
|
|
||||||
swapchain: SwapChain,
|
swapchain: SwapChain,
|
||||||
swapchain_description: SwapChainDescriptor,
|
swapchain_description: SwapChainDescriptor,
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
@@ -62,6 +65,8 @@ pub struct RenderState {
|
|||||||
pub(in crate::render) forward_pass: Pass,
|
pub(in crate::render) forward_pass: Pass,
|
||||||
pub(in crate::render) forward_depth: wgpu::TextureView,
|
pub(in crate::render) forward_depth: wgpu::TextureView,
|
||||||
|
|
||||||
|
pub(in crate::render) gbuffer_pass: Pass,
|
||||||
|
|
||||||
entity_bind_group_layout: BindGroupLayout,
|
entity_bind_group_layout: BindGroupLayout,
|
||||||
|
|
||||||
pub(in crate::render) light_uniform_buf: wgpu::Buffer,
|
pub(in crate::render) light_uniform_buf: wgpu::Buffer,
|
||||||
@@ -302,6 +307,107 @@ impl RenderState {
|
|||||||
hands-off global lighting / point lights
|
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 shadow_pass = {
|
||||||
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
|
||||||
|
|
||||||
@@ -356,14 +462,6 @@ impl RenderState {
|
|||||||
size: wgpu::BufferSize::new(uniform_size),
|
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"),
|
label: Some("Shadow uniform bind group"),
|
||||||
});
|
});
|
||||||
@@ -655,6 +753,7 @@ impl RenderState {
|
|||||||
shadow_pass,
|
shadow_pass,
|
||||||
forward_pass,
|
forward_pass,
|
||||||
forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()),
|
forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()),
|
||||||
|
gbuffer_pass: g_buffer_pass,
|
||||||
entity_bind_group_layout: entity_bind_group_layout,
|
entity_bind_group_layout: entity_bind_group_layout,
|
||||||
shadow_target_views: shadow_target_views,
|
shadow_target_views: shadow_target_views,
|
||||||
light_uniform_buf,
|
light_uniform_buf,
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ use crate::geometry::{load_obj, Vertex};
|
|||||||
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
|
||||||
use crate::light::{DirectionalLight, LightRaw};
|
use crate::light::{DirectionalLight, LightRaw};
|
||||||
use crate::render::state::RenderState;
|
use crate::render::state::RenderState;
|
||||||
use crate::render::{
|
use crate::render::{insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms, ForwardUniforms};
|
||||||
insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[system]
|
#[system]
|
||||||
#[write_component(Camera)]
|
#[write_component(Camera)]
|
||||||
@@ -235,6 +233,7 @@ pub fn render_test(
|
|||||||
mesh_stack.push(mesh.clone());
|
mesh_stack.push(mesh.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the light uniforms only if flagged
|
||||||
if renderer.lights_are_dirty {
|
if renderer.lights_are_dirty {
|
||||||
renderer.lights_are_dirty = false;
|
renderer.lights_are_dirty = false;
|
||||||
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
|
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);
|
push_debug_group_checked("shadow passes", &mut encoder);
|
||||||
|
|
||||||
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
|
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
|
||||||
@@ -327,6 +359,7 @@ pub fn render_test(
|
|||||||
|
|
||||||
let mut query = <(&mut Position, &mut Mesh)>::query();
|
let mut query = <(&mut Position, &mut Mesh)>::query();
|
||||||
|
|
||||||
|
// I could use that mesh stack here lol
|
||||||
for (pos, mesh) in query.iter_mut(world) {
|
for (pos, mesh) in query.iter_mut(world) {
|
||||||
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
pass.set_bind_group(1, &mesh.bind_group, &[]);
|
||||||
// TODO: Pipe this in through the mesh
|
// 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);
|
pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_debug_group_checked(&mut encoder);
|
pop_debug_group_checked(&mut encoder);
|
||||||
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_context = &mut imgui_context.lock().unwrap().context;
|
||||||
let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform;
|
let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform;
|
||||||
|
|||||||
Reference in New Issue
Block a user