use bevy_ecs::prelude::*;
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct GpuLight {
pub position_type: [f32; 4],
pub direction_range: [f32; 4],
pub color_intensity: [f32; 4],
pub params: [f32; 4],
}
impl Default for GpuLight {
fn default() -> Self {
Self {
position_type: [0.0; 4],
direction_range: [0.0, -1.0, 0.0, 0.0],
color_intensity: [0.0; 4],
params: [0.0; 4],
}
}
}
pub const MAX_LIGHTS: usize = 8;
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct PbrSceneUniform {
pub model: [[f32; 4]; 4], pub view_proj: [[f32; 4]; 4], pub normal_matrix: [[f32; 4]; 4], pub camera_pos: [f32; 4], pub light_dir: [f32; 4], pub light_color: [f32; 4], pub material_params: [f32; 4], pub lights: [GpuLight; MAX_LIGHTS], pub shadow_view_proj: [[f32; 4]; 4], pub emissive_factor: [f32; 4], }
impl Default for PbrSceneUniform {
fn default() -> Self {
Self {
model: glam::Mat4::IDENTITY.to_cols_array_2d(),
view_proj: glam::Mat4::IDENTITY.to_cols_array_2d(),
normal_matrix: glam::Mat4::IDENTITY.to_cols_array_2d(),
camera_pos: [0.0; 4],
light_dir: [0.0, -1.0, 0.0, 0.0],
light_color: [1.0, 1.0, 1.0, 3.0],
material_params: [0.0, 0.5, 1.0, 0.0],
lights: [GpuLight::default(); MAX_LIGHTS],
shadow_view_proj: glam::Mat4::IDENTITY.to_cols_array_2d(),
emissive_factor: [0.0; 4],
}
}
}
#[derive(Resource)]
pub struct RenderState {
pub surface_format: wgpu::TextureFormat,
pub surface_size: (u32, u32),
pub scene_uniform_buffer: wgpu::Buffer,
pub scene_bind_group: wgpu::BindGroup,
pub scene_bind_group_layout: wgpu::BindGroupLayout,
pub depth_texture_view: wgpu::TextureView,
pub hdr_texture_view: wgpu::TextureView,
pub tonemap_pipeline: wgpu::RenderPipeline,
pub tonemap_bind_group: wgpu::BindGroup,
pub tonemap_bind_group_layout: wgpu::BindGroupLayout,
pub ibl_shadow_bind_group: wgpu::BindGroup,
pub ibl_shadow_bind_group_layout: wgpu::BindGroupLayout,
pub shadow_pipeline: wgpu::RenderPipeline,
pub shadow_map_view: wgpu::TextureView,
pub hdr_msaa_texture_view: wgpu::TextureView,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pbr_scene_uniform_size() {
assert_eq!(std::mem::size_of::<PbrSceneUniform>(), 848);
}
#[test]
fn test_gpu_light_size() {
assert_eq!(std::mem::size_of::<GpuLight>(), 64);
}
#[test]
fn test_pbr_scene_uniform_default() {
let u = PbrSceneUniform::default();
assert_eq!(u.model[0][0], 1.0);
assert_eq!(u.model[1][1], 1.0);
assert_eq!(u.light_dir[1], -1.0);
assert_eq!(u.material_params[1], 0.5);
assert_eq!(u.material_params[2], 1.0);
}
}