Compare commits

..

7 Commits

2
.gitignore vendored

@ -1,3 +1 @@
/target /target
Cargo.lock
.idea/*

8
.idea/.gitignore vendored

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

@ -33,7 +33,7 @@ toml = "0.5.8"
cgmath = "0.18.0" cgmath = "0.18.0"
rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] } rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] }
nalgebra = "0.24.1" nalgebra = "0.24.1"
legion = "0.3.1" legion = "0.4.0"
wgpu = "0.7.0" wgpu = "0.7.0"
imgui = "0.7.0" imgui = "0.7.0"
imgui-wgpu = "0.14.0" imgui-wgpu = "0.14.0"

@ -0,0 +1,26 @@
# Texture Samplers
|GLSL sampler|OpenGL texture enum|Texture type|
|---|---|---|
gsampler1D | GL_TEXTURE_1D | 1D texture
gsampler2D | GL_TEXTURE_2D | 2D texture
gsampler3D | GL_TEXTURE_3D | 3D texture
gsamplerCube | GL_TEXTURE_CUBE_MAP | Cubemap Texture
gsampler2DRect | GL_TEXTURE_RECTANGLE | Rectangle Texture
gsampler1DArray | GL_TEXTURE_1D_ARRAY | 1D Array Texture
gsampler2DArray | GL_TEXTURE_2D_ARRAY | 2D Array Texture
gsamplerCubeArray | GL_TEXTURE_CUBE_MAP_ARRAY | Cubemap Array Texture
gsamplerBuffer | GL_TEXTURE_BUFFER | Buffer Texture
gsampler2DMS | GL_TEXTURE_2D_MULTISAMPLE | Multisample Texture
gsampler2DMSArray | GL_TEXTURE_2D_MULTISAMPLE_ARRAY | Multisample Array Texture
# Shadow Samplers
|GLSL sampler|OpenGL texture enum|
|---|---|
sampler1DShadow | GL_TEXTURE_1D
sampler2DShadow | GL_TEXTURE_2D
samplerCubeShadow | GL_TEXTURE_CUBE_MAP
sampler2DRectShadow | GL_TEXTURE_RECTANGLE
sampler1DArrayShadow | GL_TEXTURE_1D_ARRAY
sampler2DArrayShadow | GL_TEXTURE_2D_ARRAY
samplerCubeArrayShadow | GL_TEXTURE_CUBE_MAP_ARRAY

@ -6,6 +6,10 @@ layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj; mat4 u_ViewProj;
}; };
layout(set = 0, binding = 1) uniform Globals {
mat4 u_ViewProj;
};
layout(set = 1, binding = 0) uniform Entity { layout(set = 1, binding = 0) uniform Entity {
mat4 u_World; mat4 u_World;
vec4 u_Color; vec4 u_Color;

@ -30,18 +30,23 @@ layout(set = 1, binding = 0) uniform Entity {
}; };
float fetch_shadow(int light_id, vec4 homogeneous_coords) { float fetch_shadow(int light_id, vec4 homogeneous_coords) {
// homogeneous coords is the depth of the previously rendered
// fragment, from the lights perspective. If it's less than 0
// then it's behind the light, so it's obviously in shadow
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
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);
} }

@ -0,0 +1,22 @@
#version 450
layout(location = 0) in vec3 v_Normal;
layout(location = 1) in vec4 v_Position;
layout(location = 2) in vec2 v_Uv;
layout(location = 0) out vec4 o_Normal;
layout(location = 1) out vec4 o_Position;
layout(location = 2) out vec4 o_Uv;
// so I need to have my 3 color attachments and 1? sampler.
layout(set = 0, binding = 1) uniform texture2DArray t_Uv;
layout(set = 0, binding = 2) uniform gsampler2D s_Uv;
// I also need my 1 depth texture and its sampler
layout(set = 0, binding = 3) uniform texture2DArray t_Shadow;
layout(set = 0, binding = 4) uniform samplerShadow s_Shadow;
void main() {
}

@ -0,0 +1,21 @@
#version 450
layout(location = 0) in vec4 a_Pos;
layout(location = 0) out vec3 v_Normal;
layout(location = 1) out vec4 v_Position;
layout(location = 2) out vec2 v_Uv;
layout(set = 0, binding = 0) 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);
}

@ -45,6 +45,7 @@ use wgpu_subscriber;
use winit_24::event::DeviceEvent::MouseMotion; use winit_24::event::DeviceEvent::MouseMotion;
use winit_24::event::{ElementState, VirtualKeyCode}; use winit_24::event::{ElementState, VirtualKeyCode};
use winit_24::event_loop::EventLoopProxy; use winit_24::event_loop::EventLoopProxy;
use winit_24::platform::unix::x11::ffi::Time;
use winit_24::window::Window; use winit_24::window::Window;
use winit_24::{ use winit_24::{
event::{self, WindowEvent}, event::{self, WindowEvent},

@ -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 {}

@ -18,31 +18,35 @@ use legion::world::SubWorld;
use legion::*; use legion::*;
use rapier3d::parry::motion::RigidMotionComposition; use rapier3d::parry::motion::RigidMotionComposition;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use wgpu::{BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, Device, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, CommandEncoder}; use wgpu::{
BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device,
Features, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor,
SwapChainFrame, TextureView, VertexState,
};
use winit_24::dpi::PhysicalSize; use winit_24::dpi::PhysicalSize;
use winit_24::platform::unix::x11::ffi::Time;
use winit_24::window::Window; use winit_24::window::Window;
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
use crate::components::{Mesh, Position, RangeCopy}; use crate::components::{Mesh, Position, RangeCopy};
use crate::current_ui; use crate::current_ui;
use crate::geometry::{load_obj, Vertex, RawMesh}; 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, ShadowUniforms, ForwardUniforms}; use crate::render::{CameraProjectionView, EntityUniforms, ForwardUniforms, ShadowUniforms};
/// 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,
pub uniform_buf: wgpu::Buffer, pub uniform_buf: wgpu::Buffer,
} }
pub struct RenderState { pub struct RenderState {
swapchain: SwapChain, swapchain: SwapChain,
swapchain_description: SwapChainDescriptor, swapchain_description: SwapChainDescriptor,
instance: Arc<Instance>, instance: Arc<Instance>,
@ -60,6 +64,15 @@ 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,
// Gbuffer bs
pub(in crate::render) gbuffer_pass: Pass,
pub(in crate::render) gbuffer_cam_projection_buffer: wgpu::Buffer,
pub(in crate::render) gbuffer_depth_texture: wgpu::TextureView,
pub(in crate::render) gbuffer_depth_views: Vec<Arc<TextureView>>,
pub(in crate::render) gbuffer_target_texture: wgpu::TextureView,
pub(in crate::render) gbuffer_target_views: Vec<Arc<TextureView>>,
// this is for the set=1 entity uniforms
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,
@ -72,12 +85,14 @@ pub struct RenderState {
impl RenderState { impl RenderState {
const MAX_LIGHTS: usize = 10; const MAX_LIGHTS: usize = 10;
const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float; const SHADOW_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
const G_BUFFER_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba32Float;
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d { const SHADOW_SIZE: wgpu::Extent3d = wgpu::Extent3d {
width: 1024, width: 1024,
height: 1024, height: 1024,
depth: Self::MAX_LIGHTS as u32, depth: Self::MAX_LIGHTS as u32,
}; };
const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
/// Generate a projection matrix with no look-at yet /// Generate a projection matrix with no look-at yet
pub fn generate_matrix(&self) -> cgmath::Matrix4<f32> { pub fn generate_matrix(&self) -> cgmath::Matrix4<f32> {
@ -108,10 +123,7 @@ impl RenderState {
} }
/// Create a buffer for a mesh /// Create a buffer for a mesh
fn create_buffer( fn create_buffer(device: &wgpu::Device, raw_mesh: &RawMesh) -> (Arc<Buffer>, Arc<Buffer>) {
device: &wgpu::Device,
raw_mesh: &RawMesh,
) -> (Arc<Buffer>, Arc<Buffer>) {
let vertex_buf = Arc::new( let vertex_buf = Arc::new(
device.create_buffer_init(&wgpu::util::BufferInitDescriptor { device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("vertex-buffer"), label: Some("vertex-buffer"),
@ -132,8 +144,11 @@ impl RenderState {
} }
/// Take a meshes raw representation and upload it to a GPU buffer /// Take a meshes raw representation and upload it to a GPU buffer
pub fn upload_mesh_to_buffer(&mut self, mesh: &RawMesh, color: Option<wgpu::Color>) -> Result<Mesh, String> { pub fn upload_mesh_to_buffer(
&mut self,
mesh: &RawMesh,
color: Option<wgpu::Color>,
) -> Result<Mesh, String> {
let index_count = mesh.indices.len() * 3; // TODO bad bad bad bad! let index_count = mesh.indices.len() * 3; // TODO bad bad bad bad!
let (vertex_buf, index_buf) = RenderState::create_buffer(&self.device, mesh); let (vertex_buf, index_buf) = RenderState::create_buffer(&self.device, mesh);
@ -173,7 +188,11 @@ impl RenderState {
} }
/// explicitly load from file, and upload to gpu the mesh /// explicitly load from file, and upload to gpu the mesh
pub fn load_mesh_to_buffer(&mut self, filepath: &str, color: Option<wgpu::Color>) -> Result<Mesh, String> { pub fn load_mesh_to_buffer(
&mut self,
filepath: &str,
color: Option<wgpu::Color>,
) -> Result<Mesh, String> {
let raw_mesh = load_obj(filepath)?; let raw_mesh = load_obj(filepath)?;
self.upload_mesh_to_buffer(&raw_mesh, color) self.upload_mesh_to_buffer(&raw_mesh, color)
} }
@ -204,6 +223,105 @@ impl RenderState {
} }
} }
// Create a render pass with the ability to add external bindings
pub fn create_render_pass(
device: &Device,
external_binding_layout: &BindGroupLayout,
vertex_description: &wgpu::VertexBufferLayout,
uniform_size: u64,
label: Option<&str>,
) -> Option<Pass> {
// The g-buffers camera projection matrix that we stream data to
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some(format!("{} uniform-buffer", label.unwrap_or("unnamed")).as_str()),
size: uniform_size,
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
mapped_at_creation: false,
});
// Uniform bind group for the view matrix
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some(format!("{} bind group layout", label.unwrap_or("unnamed")).as_str()),
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,
}],
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some(format!("{} uniform bind group", label.unwrap_or("unnamed")).as_str()),
layout: &bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniform_buf,
offset: 0,
size: wgpu::BufferSize::new(uniform_size),
},
}],
});
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"));
// The bind group layouts are accessed by layout(set = X, binding = x)
// in the shader.
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some(format!("{} pipeline layout", label.unwrap_or("unnamed")).as_str()),
bind_group_layouts: &[&bind_group_layout, external_binding_layout],
push_constant_ranges: &[],
});
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some(format!("{} render pipeline", label.unwrap_or("unnamed")).as_str()),
layout: Some(&pipeline_layout),
vertex: VertexState {
module: &vs_module,
entry_point: "main",
buffers: &[vertex_description.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: wgpu::TextureFormat::Depth32Float,
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(),
});
Some(Pass {
pipeline,
bind_group,
uniform_buf,
})
}
pub fn init(window: &Window, imgui_context: &mut ImguiContext) -> RenderState { pub fn init(window: &Window, imgui_context: &mut ImguiContext) -> RenderState {
// Grab the GPU instance, and query its features // Grab the GPU instance, and query its features
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY); let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
@ -291,10 +409,149 @@ impl RenderState {
}); });
/* /*
There appear to be two passes required for shadows, the shadow pass, and the forward pass The shadow pass renders from the perspective of each camera and applies that to the shadow
Need to open this up in renderdoc and see what it's actually doing texture. Due to light FOV and the shadow texture itself, it's rather difficult to have
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 = Self::create_render_pass(
&device,
&entity_bind_group_layout,
&vb_desc,
mem::size_of::<CameraProjectionView>() as wgpu::BufferAddress,
Some("g-buffer"),
);
let shadow_pass = Self::create_render_pass(
&device,
&entity_bind_group_layout,
&vb_desc,
mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress,
Some("shadow-pass"),
);
let g_buffer_pass = {
let uniform_size = mem::size_of::<CameraProjectionView>() as wgpu::BufferAddress;
// The g-buffers camera projection matrix that we stream data to
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("g-buffers CameraProjectionView uniform buffer"),
size: uniform_size,
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
mapped_at_creation: false,
});
// Uniform bind group for the view matrix
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,
},
wgpu::BindGroupLayoutEntry {
binding: 1, // texture2DArray
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture {
multisampled: false,
sample_type: wgpu::TextureSampleType::Depth,
view_dimension: wgpu::TextureViewDimension::D2Array,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 2, // samplerShadow
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler {
filtering: false,
comparison: true,
},
count: None,
},
],
});
//sudo rm /usr/bin/ld
//sudo ln -s /usr/bin/lld /usr/bin/ld
//sudo ln -s /usr/bin/x86_64-linux-gnu-ld /usr/bin/ld
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("g-buffers uniform bind group"),
layout: &bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0, // globals
resource: wgpu::BindingResource::Buffer {
buffer: &uniform_buf,
offset: 0,
size: wgpu::BufferSize::new(uniform_size),
},
}],
});
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"));
// The bind group layouts are accessed by layout(set = X, binding = x)
// in the shader.
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: &[],
});
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("g-buffer"),
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: wgpu::TextureFormat::Depth32Float,
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;
@ -345,9 +602,9 @@ impl RenderState {
// Create the render pipeline // Create the render pipeline
let vs_module = let vs_module =
device.create_shader_module(&wgpu::include_spirv!("../../resources/bake.vert.spv")); device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.vert.spv"));
let fs_module = let fs_module =
device.create_shader_module(&wgpu::include_spirv!("../../resources/bake.frag.spv")); device.create_shader_module(&wgpu::include_spirv!("../../shaders/bake.frag.spv"));
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("shadow"), label: Some("shadow"),
@ -391,6 +648,19 @@ impl RenderState {
} }
}; };
// Pre init the gbuffers camera projection uniform
let gbuffer_cam_uniform_size =
mem::size_of::<CameraProjectionView>() as wgpu::BufferAddress;
let gbuffer_cam_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("g-buffer camera projection uniform buffer"),
size: gbuffer_cam_uniform_size,
usage: wgpu::BufferUsage::UNIFORM
| wgpu::BufferUsage::COPY_SRC
| wgpu::BufferUsage::COPY_DST,
mapped_at_creation: false,
});
// Pre init the light uniform, with slots enough for MAX_LIGHTS // Pre init the light uniform, with slots enough for MAX_LIGHTS
let light_uniform_size = let light_uniform_size =
(Self::MAX_LIGHTS * mem::size_of::<LightRaw>()) as wgpu::BufferAddress; (Self::MAX_LIGHTS * mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
@ -436,8 +706,22 @@ impl RenderState {
50.0, 50.0,
); );
let g_buffer_camera_projection_matrix = CameraProjectionView {
proj: *mx_projection.as_ref(),
};
let g_buffer_camera_projection_uniform =
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("g-buffer camera projection uniform buffer"),
contents: bytemuck::bytes_of(&g_buffer_camera_projection_matrix),
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
});
let forward_pass = { let forward_pass = {
// Create pipeline layout // Create pipeline layout
let forward_uniform_size =
mem::size_of::<ForwardUniforms>() as wgpu::BufferAddress;
let bind_group_layout = let bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[ entries: &[
@ -446,11 +730,7 @@ impl RenderState {
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Buffer { ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform, ty: wgpu::BufferBindingType::Uniform,
min_binding_size: wgpu::BufferSize::new(mem::size_of::< min_binding_size: wgpu::BufferSize::new(forward_uniform_size),
ForwardUniforms,
>(
)
as _),
has_dynamic_offset: false, has_dynamic_offset: false,
}, },
count: None, count: None,
@ -466,7 +746,7 @@ impl RenderState {
count: None, count: None,
}, },
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 2, binding: 2, // texture2DArray
visibility: wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Texture { ty: wgpu::BindingType::Texture {
multisampled: false, multisampled: false,
@ -476,7 +756,7 @@ impl RenderState {
count: None, count: None,
}, },
wgpu::BindGroupLayoutEntry { wgpu::BindGroupLayoutEntry {
binding: 3, binding: 3, // samplerShadow
visibility: wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler { ty: wgpu::BindingType::Sampler {
filtering: false, filtering: false,
@ -558,10 +838,10 @@ impl RenderState {
}); });
// Create the render pipeline // Create the render pipeline
let vs_module = let vs_module = device
device.create_shader_module(&wgpu::include_spirv!("../../resources/forward.vert.spv")); .create_shader_module(&wgpu::include_spirv!("../../shaders/forward.vert.spv"));
let fs_module = let fs_module = device
device.create_shader_module(&wgpu::include_spirv!("../../resources/forward.frag.spv")); .create_shader_module(&wgpu::include_spirv!("../../shaders/forward.frag.spv"));
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("main"), label: Some("main"),
@ -599,7 +879,7 @@ impl RenderState {
} }
}; };
let depth_texture = device.create_texture(&wgpu::TextureDescriptor { let forward_depth_texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d { size: wgpu::Extent3d {
width: sc_desc.width, width: sc_desc.width,
height: sc_desc.height, height: sc_desc.height,
@ -610,9 +890,73 @@ impl RenderState {
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT, format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT, usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
label: Some("Depth Texture"), label: Some("Forward Depth Texture"),
}); });
let g_buffer_depth_texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
depth: 5,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
label: Some("g-buffer depth texture"),
});
// I need one of these for each of the g-buffer elements I'm calculating
let mut g_buffer_depth_texture_views = (0..4)
.map(|i| {
Arc::new(
g_buffer_depth_texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("g-buffer depth texture"),
format: None,
dimension: Some(wgpu::TextureViewDimension::D2),
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
level_count: None,
base_array_layer: i as u32,
array_layer_count: NonZeroU32::new(1),
}),
)
})
.collect::<Vec<_>>();
let g_buffer_data_texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
depth: 5,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::RENDER_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
label: Some("g-buffer depth texture"),
});
// I need one of these for each of the g-buffer elements I'm calculating
let mut g_buffer_data_texture_views = (0..4)
.map(|i| {
Arc::new(
g_buffer_depth_texture.create_view(&wgpu::TextureViewDescriptor {
label: Some("g-buffer depth texture"),
format: None,
dimension: Some(wgpu::TextureViewDimension::D2),
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
level_count: None,
base_array_layer: i as u32,
array_layer_count: NonZeroU32::new(1),
}),
)
})
.collect::<Vec<_>>();
// Imgui renderer // Imgui renderer
let renderer_config = ImguiRendererConfig { let renderer_config = ImguiRendererConfig {
texture_format: sc_desc.format, texture_format: sc_desc.format,
@ -622,6 +966,15 @@ impl RenderState {
ImguiRenderer::new(&mut imgui_context.context, &device, &queue, renderer_config); ImguiRenderer::new(&mut imgui_context.context, &device, &queue, renderer_config);
RenderState { RenderState {
gbuffer_pass: g_buffer_pass,
gbuffer_cam_projection_buffer: g_buffer_camera_projection_uniform,
gbuffer_depth_texture: g_buffer_depth_texture
.create_view(&wgpu::TextureViewDescriptor::default()),
gbuffer_depth_views: g_buffer_depth_texture_views,
gbuffer_target_texture: g_buffer_data_texture
.create_view(&wgpu::TextureViewDescriptor::default()),
gbuffer_target_views: g_buffer_data_texture_views,
swapchain: swap_chain, swapchain: swap_chain,
queue: queue, queue: queue,
size, size,
@ -629,7 +982,8 @@ impl RenderState {
lights_are_dirty: true, lights_are_dirty: true,
shadow_pass, shadow_pass,
forward_pass, forward_pass,
forward_depth: depth_texture.create_view(&wgpu::TextureViewDescriptor::default()), forward_depth: forward_depth_texture
.create_view(&wgpu::TextureViewDescriptor::default()),
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,
@ -684,7 +1038,6 @@ impl RenderState {
} }
} }
/* /*

@ -1,31 +1,32 @@
use std::{iter, num::NonZeroU32, ops::Range, rc::Rc};
use std::cell::RefCell; use std::cell::RefCell;
use std::iter::Chain; use std::iter::Chain;
use std::slice::Iter; use std::slice::Iter;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::current; use std::thread::current;
use std::time::Duration; use std::time::Duration;
use std::{iter, num::NonZeroU32, ops::Range, rc::Rc};
use bytemuck::__core::mem;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use bytemuck::__core::mem;
use cgmath::{ use cgmath::{
vec3, Decomposed, Deg, Euler, InnerSpace, Matrix4, Point3, Quaternion, Rad, Rotation3, Decomposed, Deg, Euler, InnerSpace, Matrix4, Point3, Quaternion, Rad, Rotation3, Transform,
Transform, Vector3, vec3, Vector3,
}; };
use futures::executor::LocalPool; use futures::executor::LocalPool;
use imgui::sys::ImGuiContext;
use imgui::*; use imgui::*;
use imgui::sys::ImGuiContext;
use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig};
use legion::world::SubWorld;
use legion::*; use legion::*;
use legion::world::SubWorld;
use rapier3d::parry::motion::RigidMotionComposition; use rapier3d::parry::motion::RigidMotionComposition;
use wgpu::util::DeviceExt;
use wgpu::{ use wgpu::{
BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device, BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device,
FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame,
TextureView, VertexState, TextureView, VertexState,
}; };
use wgpu::util::DeviceExt;
use winit_24::dpi::PhysicalSize; use winit_24::dpi::PhysicalSize;
use winit_24::platform::unix::x11::ffi::Time;
use winit_24::window::Window; use winit_24::window::Window;
use crate::camera::{Camera, CameraController}; use crate::camera::{Camera, CameraController};
@ -34,10 +35,8 @@ use crate::current_ui;
use crate::geometry::{load_obj, Vertex}; 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::{EntityUniforms, ForwardUniforms, insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked};
use crate::render::state::RenderState; use crate::render::state::RenderState;
use crate::render::{
insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms,
};
#[system] #[system]
#[write_component(Camera)] #[write_component(Camera)]
@ -80,6 +79,7 @@ fn run_imgui_render_step<G: 'static + Sized + Send + Sync>(world: &mut SubWorld,
.build(&ui, || (window_func.unwrap())(ui, v)); .build(&ui, || (window_func.unwrap())(ui, v));
} }
} }
/// Go through each "global" window-data component and render it's data /// Go through each "global" window-data component and render it's data
#[system] #[system]
#[write_component(ImguiWindow < ImguiPerformanceProfilerLine >)] #[write_component(ImguiWindow < ImguiPerformanceProfilerLine >)]
@ -234,6 +234,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();
@ -246,10 +247,58 @@ pub fn render_test(
} }
} }
push_debug_group_checked("shadow passes", &mut encoder); // Render the g buffer
push_debug_group_checked("g-buffer stuff", &mut encoder);
{
// insert_debug_marker_checked("render entities", &mut encoder);
let mut query = <(&mut DirectionalLight, &mut Position)>::query(); // The render pass for the g buffer.. Does it need any attachments
// the shadow pass uses a target view as the input, which are just views on
// top of the shadow texture. So the attachment is a RW buffer which clears on load
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("render pass"),
color_attachments: &[
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &renderer.gbuffer_target_views.get(0).unwrap(),
resolve_target: None,
ops: Default::default(),
},
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &renderer.gbuffer_target_views.get(1).unwrap(),
resolve_target: None,
ops: Default::default(),
},
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &renderer.gbuffer_target_views.get(2).unwrap(),
resolve_target: None,
ops: Default::default(),
}],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: &renderer.gbuffer_target_views.get(3).unwrap(),
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: true,
}),
stencil_ops: None,
}),
});
pass.set_pipeline(&renderer.gbuffer_pass.pipeline);
pass.set_bind_group(0, &renderer.gbuffer_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);
// Render the shadow textures
push_debug_group_checked("shadow passes", &mut encoder);
let mut query = <(&mut DirectionalLight, &mut Position)>::query();
for (i, (light, pos)) in query.iter_mut(world).enumerate() { for (i, (light, pos)) in query.iter_mut(world).enumerate() {
insert_debug_marker_checked( insert_debug_marker_checked(
&format!("shadow pass {} (light at position {:?})", i, pos), &format!("shadow pass {} (light at position {:?})", i, pos),
@ -268,6 +317,7 @@ pub fn render_test(
insert_debug_marker_checked("render entities", &mut encoder); insert_debug_marker_checked("render entities", &mut encoder);
//
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("render pass"), label: Some("render pass"),
color_attachments: &[], color_attachments: &[],
@ -291,11 +341,10 @@ 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);
// forward pass
push_debug_group_checked("forward rendering pass", &mut encoder);
// And then render the viewport
push_debug_group_checked("forward rendering pass", &mut encoder);
{ {
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("forward render pass"), label: Some("forward render pass"),
@ -326,6 +375,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
@ -334,9 +384,12 @@ 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);
// Run the Imgui render
push_debug_group_checked("imgui rendering pass", &mut encoder);
{ {
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;
@ -371,6 +424,10 @@ pub fn render_test(
.render(draw_data, &renderer.queue, &renderer.device, &mut rpass) .render(draw_data, &renderer.queue, &renderer.device, &mut rpass)
.expect("Rendering failed"); .expect("Rendering failed");
} }
pop_debug_group_checked(&mut encoder);
// the startfunction debug group
pop_debug_group_checked(&mut encoder);
renderer.queue.submit(iter::once(encoder.finish())); renderer.queue.submit(iter::once(encoder.finish()));
} }

Loading…
Cancel
Save