#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GBufferSlot {
Albedo,
Normal,
Roughness,
Metallic,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct GBuffer {
pub width: u32,
pub height: u32,
pub data: Vec<Vec<f32>>,
}
#[allow(dead_code)]
pub fn new_gbuffer(width: u32, height: u32) -> GBuffer {
let n = (width * height * 4) as usize;
GBuffer { width, height, data: vec![vec![0.0; n]; 4] }
}
#[allow(dead_code)]
pub fn gbuffer_write_albedo(gb: &mut GBuffer, x: u32, y: u32, rgba: [f32; 4]) {
gbuffer_write_slot(gb, GBufferSlot::Albedo, x, y, rgba);
}
#[allow(dead_code)]
pub fn gbuffer_write_normal(gb: &mut GBuffer, x: u32, y: u32, rgba: [f32; 4]) {
gbuffer_write_slot(gb, GBufferSlot::Normal, x, y, rgba);
}
#[allow(dead_code)]
pub fn gbuffer_write_roughness(gb: &mut GBuffer, x: u32, y: u32, value: f32) {
gbuffer_write_slot(gb, GBufferSlot::Roughness, x, y, [value, 0.0, 0.0, 0.0]);
}
fn gbuffer_write_slot(gb: &mut GBuffer, slot: GBufferSlot, x: u32, y: u32, rgba: [f32; 4]) {
let idx = slot as usize;
let base = ((y * gb.width + x) * 4) as usize;
if idx < gb.data.len() && base + 3 < gb.data[idx].len() {
gb.data[idx][base..base + 4].copy_from_slice(&rgba);
}
}
#[allow(dead_code)]
pub fn gbuffer_read(gb: &GBuffer, slot: GBufferSlot, x: u32, y: u32) -> [f32; 4] {
let idx = slot as usize;
let base = ((y * gb.width + x) * 4) as usize;
if idx < gb.data.len() && base + 3 < gb.data[idx].len() {
[gb.data[idx][base], gb.data[idx][base + 1], gb.data[idx][base + 2], gb.data[idx][base + 3]]
} else {
[0.0; 4]
}
}
#[allow(dead_code)]
pub fn gbuffer_clear(gb: &mut GBuffer) {
for slot in &mut gb.data {
slot.fill(0.0);
}
}
#[allow(dead_code)]
pub fn gbuffer_slot_count(_gb: &GBuffer) -> usize {
4
}
#[allow(dead_code)]
pub fn gbuffer_dimensions(gb: &GBuffer) -> (u32, u32) {
(gb.width, gb.height)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_gbuffer_zeroed() {
let gb = new_gbuffer(2, 2);
assert!(gb.data.iter().all(|slot| slot.iter().all(|&v| v == 0.0)));
}
#[test]
fn test_gbuffer_dimensions() {
let gb = new_gbuffer(8, 6);
assert_eq!(gbuffer_dimensions(&gb), (8, 6));
}
#[test]
fn test_gbuffer_slot_count() {
let gb = new_gbuffer(1, 1);
assert_eq!(gbuffer_slot_count(&gb), 4);
}
#[test]
fn test_write_read_albedo() {
let mut gb = new_gbuffer(4, 4);
gbuffer_write_albedo(&mut gb, 1, 1, [1.0, 0.5, 0.25, 1.0]);
let v = gbuffer_read(&gb, GBufferSlot::Albedo, 1, 1);
assert!((v[0] - 1.0).abs() < 1e-6);
assert!((v[1] - 0.5).abs() < 1e-6);
}
#[test]
fn test_write_read_normal() {
let mut gb = new_gbuffer(4, 4);
gbuffer_write_normal(&mut gb, 0, 0, [0.0, 1.0, 0.0, 0.0]);
let v = gbuffer_read(&gb, GBufferSlot::Normal, 0, 0);
assert!((v[1] - 1.0).abs() < 1e-6);
}
#[test]
fn test_write_roughness() {
let mut gb = new_gbuffer(4, 4);
gbuffer_write_roughness(&mut gb, 2, 2, 0.8);
let v = gbuffer_read(&gb, GBufferSlot::Roughness, 2, 2);
assert!((v[0] - 0.8).abs() < 1e-6);
}
#[test]
fn test_gbuffer_clear() {
let mut gb = new_gbuffer(2, 2);
gbuffer_write_albedo(&mut gb, 0, 0, [1.0, 1.0, 1.0, 1.0]);
gbuffer_clear(&mut gb);
let v = gbuffer_read(&gb, GBufferSlot::Albedo, 0, 0);
assert!(v.iter().all(|&c| c == 0.0));
}
#[test]
fn test_gbuffer_slot_enum_distinct() {
assert_ne!(GBufferSlot::Albedo, GBufferSlot::Normal);
assert_ne!(GBufferSlot::Roughness, GBufferSlot::Metallic);
}
#[test]
fn test_gbuffer_out_of_bounds_read_returns_zero() {
let gb = new_gbuffer(2, 2);
let v = gbuffer_read(&gb, GBufferSlot::Albedo, 100, 100);
assert!(v.iter().all(|&c| c == 0.0));
}
}