feat(renderer): add GBuffer and fullscreen triangle for deferred rendering
Introduces GBuffer struct with 4 render target TextureViews (position/ normal/albedo/material) plus depth, and a fullscreen oversized triangle for screen-space passes. Exports format constants and create helpers. Updates lib.rs with new module declarations and re-exports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
38
crates/voltex_renderer/src/fullscreen_quad.rs
Normal file
38
crates/voltex_renderer/src/fullscreen_quad.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Pod, Zeroable)]
|
||||
pub struct FullscreenVertex {
|
||||
pub position: [f32; 2],
|
||||
}
|
||||
|
||||
impl FullscreenVertex {
|
||||
pub const LAYOUT: wgpu::VertexBufferLayout<'static> = wgpu::VertexBufferLayout {
|
||||
array_stride: std::mem::size_of::<FullscreenVertex>() as wgpu::BufferAddress,
|
||||
step_mode: wgpu::VertexStepMode::Vertex,
|
||||
attributes: &[
|
||||
wgpu::VertexAttribute {
|
||||
offset: 0,
|
||||
shader_location: 0,
|
||||
format: wgpu::VertexFormat::Float32x2,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/// Oversized triangle covering the entire screen (clip-space).
|
||||
/// Three vertices: (-1,-1), (3,-1), (-1,3)
|
||||
pub const FULLSCREEN_VERTICES: [FullscreenVertex; 3] = [
|
||||
FullscreenVertex { position: [-1.0, -1.0] },
|
||||
FullscreenVertex { position: [ 3.0, -1.0] },
|
||||
FullscreenVertex { position: [-1.0, 3.0] },
|
||||
];
|
||||
|
||||
pub fn create_fullscreen_vertex_buffer(device: &wgpu::Device) -> wgpu::Buffer {
|
||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Fullscreen Triangle Vertex Buffer"),
|
||||
contents: bytemuck::cast_slice(&FULLSCREEN_VERTICES),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
})
|
||||
}
|
||||
70
crates/voltex_renderer/src/gbuffer.rs
Normal file
70
crates/voltex_renderer/src/gbuffer.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use crate::gpu::DEPTH_FORMAT;
|
||||
|
||||
pub const GBUFFER_POSITION_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba32Float;
|
||||
pub const GBUFFER_NORMAL_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba16Float;
|
||||
pub const GBUFFER_ALBEDO_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8UnormSrgb;
|
||||
pub const GBUFFER_MATERIAL_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm;
|
||||
|
||||
fn create_rt(
|
||||
device: &wgpu::Device,
|
||||
w: u32,
|
||||
h: u32,
|
||||
format: wgpu::TextureFormat,
|
||||
label: &str,
|
||||
) -> wgpu::TextureView {
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some(label),
|
||||
size: wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 },
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
});
|
||||
texture.create_view(&wgpu::TextureViewDescriptor::default())
|
||||
}
|
||||
|
||||
fn create_depth(device: &wgpu::Device, w: u32, h: u32) -> wgpu::TextureView {
|
||||
let texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: Some("GBuffer Depth Texture"),
|
||||
size: wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 },
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: DEPTH_FORMAT,
|
||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
||||
view_formats: &[],
|
||||
});
|
||||
texture.create_view(&wgpu::TextureViewDescriptor::default())
|
||||
}
|
||||
|
||||
pub struct GBuffer {
|
||||
pub position_view: wgpu::TextureView,
|
||||
pub normal_view: wgpu::TextureView,
|
||||
pub albedo_view: wgpu::TextureView,
|
||||
pub material_view: wgpu::TextureView,
|
||||
pub depth_view: wgpu::TextureView,
|
||||
}
|
||||
|
||||
impl GBuffer {
|
||||
pub fn new(device: &wgpu::Device, width: u32, height: u32) -> Self {
|
||||
let position_view = create_rt(device, width, height, GBUFFER_POSITION_FORMAT, "GBuffer Position");
|
||||
let normal_view = create_rt(device, width, height, GBUFFER_NORMAL_FORMAT, "GBuffer Normal");
|
||||
let albedo_view = create_rt(device, width, height, GBUFFER_ALBEDO_FORMAT, "GBuffer Albedo");
|
||||
let material_view = create_rt(device, width, height, GBUFFER_MATERIAL_FORMAT, "GBuffer Material");
|
||||
let depth_view = create_depth(device, width, height);
|
||||
|
||||
Self {
|
||||
position_view,
|
||||
normal_view,
|
||||
albedo_view,
|
||||
material_view,
|
||||
depth_view,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, device: &wgpu::Device, width: u32, height: u32) {
|
||||
*self = Self::new(device, width, height);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ pub mod shadow;
|
||||
pub mod shadow_pipeline;
|
||||
pub mod brdf_lut;
|
||||
pub mod ibl;
|
||||
pub mod gbuffer;
|
||||
pub mod fullscreen_quad;
|
||||
pub mod deferred_pipeline;
|
||||
|
||||
pub use gpu::{GpuContext, DEPTH_FORMAT};
|
||||
pub use light::{CameraUniform, LightUniform, LightData, LightsUniform, MAX_LIGHTS, LIGHT_DIRECTIONAL, LIGHT_POINT, LIGHT_SPOT};
|
||||
@@ -25,3 +28,10 @@ pub use pbr_pipeline::create_pbr_pipeline;
|
||||
pub use shadow::{ShadowMap, ShadowUniform, ShadowPassUniform, SHADOW_MAP_SIZE, SHADOW_FORMAT};
|
||||
pub use shadow_pipeline::{create_shadow_pipeline, shadow_pass_bind_group_layout};
|
||||
pub use ibl::IblResources;
|
||||
pub use gbuffer::GBuffer;
|
||||
pub use fullscreen_quad::{create_fullscreen_vertex_buffer, FullscreenVertex};
|
||||
pub use deferred_pipeline::{
|
||||
create_gbuffer_pipeline, create_lighting_pipeline,
|
||||
gbuffer_camera_bind_group_layout,
|
||||
lighting_gbuffer_bind_group_layout, lighting_lights_bind_group_layout, lighting_shadow_bind_group_layout,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user