Skip to main content

oxihuman_export/
render_pass_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Export render pass configuration.
6
7/* ── legacy API (kept) ── */
8
9#[derive(Debug, Clone)]
10pub struct RenderPassEntry {
11    pub name: String,
12    pub pass_type: String,
13    pub enabled: bool,
14    pub samples: u32,
15}
16
17#[derive(Debug, Clone, Default)]
18pub struct RenderPassExport {
19    pub passes: Vec<RenderPassEntry>,
20}
21
22pub fn new_render_pass_export() -> RenderPassExport {
23    RenderPassExport { passes: Vec::new() }
24}
25
26pub fn add_render_pass(exp: &mut RenderPassExport, name: &str, type_: &str, samples: u32) {
27    exp.passes.push(RenderPassEntry {
28        name: name.to_string(),
29        pass_type: type_.to_string(),
30        enabled: true,
31        samples,
32    });
33}
34
35/* ── spec functions (wave 150B) ── */
36
37/// Spec-style render pass (a 2D pixel buffer).
38#[derive(Debug, Clone)]
39pub struct RenderPass {
40    pub name: String,
41    pub width: usize,
42    pub height: usize,
43    pub pixels: Vec<f32>,
44}
45
46/// Create a new zeroed `RenderPass`.
47pub fn new_render_pass(name: &str, width: usize, height: usize) -> RenderPass {
48    RenderPass {
49        name: name.to_string(),
50        width,
51        height,
52        pixels: vec![0.0; width * height],
53    }
54}
55
56/// Set a pixel value at (x, y).
57pub fn pass_set_pixel(pass: &mut RenderPass, x: usize, y: usize, value: f32) {
58    if x < pass.width && y < pass.height {
59        pass.pixels[y * pass.width + x] = value;
60    }
61}
62
63/// Get a pixel value at (x, y).
64pub fn pass_get_pixel(pass: &RenderPass, x: usize, y: usize) -> f32 {
65    if x < pass.width && y < pass.height {
66        pass.pixels[y * pass.width + x]
67    } else {
68        0.0
69    }
70}
71
72/// Return pixel data as bytes (f32 → 4 bytes each, little-endian).
73pub fn pass_to_bytes(pass: &RenderPass) -> Vec<u8> {
74    pass.pixels.iter().flat_map(|&f| f.to_le_bytes()).collect()
75}
76
77/// Mean pixel value.
78pub fn pass_mean(pass: &RenderPass) -> f32 {
79    if pass.pixels.is_empty() {
80        return 0.0;
81    }
82    pass.pixels.iter().sum::<f32>() / pass.pixels.len() as f32
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_new_render_pass() {
91        let p = new_render_pass("beauty", 4, 4);
92        assert_eq!(p.pixels.len(), 16);
93    }
94
95    #[test]
96    fn test_set_get_pixel() {
97        let mut p = new_render_pass("r", 4, 4);
98        pass_set_pixel(&mut p, 1, 2, 0.5);
99        assert!((pass_get_pixel(&p, 1, 2) - 0.5).abs() < 1e-5);
100    }
101
102    #[test]
103    fn test_pass_to_bytes_len() {
104        let p = new_render_pass("r", 2, 2);
105        assert_eq!(pass_to_bytes(&p).len(), 16);
106    }
107
108    #[test]
109    fn test_pass_mean_zero() {
110        let p = new_render_pass("r", 2, 2);
111        assert!((pass_mean(&p)).abs() < 1e-5);
112    }
113
114    #[test]
115    fn test_pass_mean_nonzero() {
116        let mut p = new_render_pass("r", 2, 1);
117        pass_set_pixel(&mut p, 0, 0, 1.0);
118        pass_set_pixel(&mut p, 1, 0, 1.0);
119        assert!((pass_mean(&p) - 1.0).abs() < 1e-5);
120    }
121}