perf: writer

This commit is contained in:
dengqn 2025-08-05 14:13:47 +08:00
parent 71ae83d205
commit f60a06d84b
5 changed files with 94 additions and 23 deletions

View File

@ -1,10 +1,14 @@
use std::fs::File;
use std::io::{BufWriter};
use crate::hittable::HittableList; use crate::hittable::HittableList;
use crate::math_utils::clamp; use crate::math_utils::clamp;
use crate::ppm_writer::PPMWriter;
use crate::types_defined::{Camera, Color, Point, Ray, Vec3}; use crate::types_defined::{Camera, Color, Point, Ray, Vec3};
use rand::rngs::ThreadRng; use rand::rngs::ThreadRng;
use rand::{Rng, thread_rng}; use rand::{Rng, thread_rng};
impl Camera { impl<'a> Camera<'a> {
pub fn new( pub fn new(
image_width: i32, image_width: i32,
aspect_ratio: f32, aspect_ratio: f32,
@ -12,7 +16,8 @@ impl Camera {
camera_center: Point, camera_center: Point,
focal_length: Vec3, focal_length: Vec3,
sample_times: i8, sample_times: i8,
reflect_depth: i8 reflect_depth: i8,
ppm_file_writer: &'a mut PPMWriter<BufWriter<File>>
) -> Self { ) -> Self {
let image_height = ((image_width as f32 / aspect_ratio) as i32).max(1); let image_height = ((image_width as f32 / aspect_ratio) as i32).max(1);
let viewport_width = viewport_height * (image_width as f32 / image_height as f32); let viewport_width = viewport_height * (image_width as f32 / image_height as f32);
@ -48,11 +53,12 @@ impl Camera {
viewport_top_left_pixel_center, viewport_top_left_pixel_center,
sample_times, sample_times,
reflect_depth, reflect_depth,
ppm_file_writer
} }
} }
pub fn render(&self, world: &HittableList) -> String { pub fn render(&mut self, world: &HittableList) {
let mut img_content = format!("P3\n{} {}\n255\n", self.image_width, self.image_height); // let mut img_content = format!("P3\n{} {}\n255\n", self.image_width, self.image_height);
for j in 0..self.image_height { for j in 0..self.image_height {
if j % 10 == 0 { if j % 10 == 0 {
@ -63,7 +69,7 @@ impl Camera {
// color // color
let mut color = Color::new(0.0, 0.0, 0.0); let mut color = Color::new(0.0, 0.0, 0.0);
let rng = &mut thread_rng(); let rng = &mut thread_rng();
for s in 0..self.sample_times { for _ in 0..self.sample_times {
let bias = self.random_square(rng); let bias = self.random_square(rng);
let pix_sample = self.viewport_top_left_pixel_center let pix_sample = self.viewport_top_left_pixel_center
+ (i as f32 + bias.x) * self.viewport_u_delta + (i as f32 + bias.x) * self.viewport_u_delta
@ -82,13 +88,16 @@ impl Camera {
clamp(color.z, 0.0, 1.0), clamp(color.z, 0.0, 1.0),
); );
self.ppm_file_writer.write(color.to_color());
// content // content
img_content.push_str(color_clamped.to_color().as_str()); // img_content.push_str(&color_clamped.to_color_str().as_str());
img_content.push('\n'); // img_content.push('\n');
} }
} }
img_content // img_content
} }
fn ray_color(&self, ray: &Ray, depth: i8, world: &HittableList) -> Vec3 { fn ray_color(&self, ray: &Ray, depth: i8, world: &HittableList) -> Vec3 {

View File

@ -1,7 +1,10 @@
use crate::types_defined::Color; use crate::types_defined::Color;
impl Color { impl Color {
pub fn to_color(self) -> String { pub fn to_color(self) -> Self {
return Color::new(self.x * 256.0 , self.y * 256.0, self.z * 256.0);
}
pub fn to_color_str(self) -> String {
return format!("{} {} {}\n", (self.x * 256.0) as u8, (self.y * 256.0) as u8, (self.z * 256.0) as u8); return format!("{} {} {}\n", (self.x * 256.0) as u8, (self.y * 256.0) as u8, (self.z * 256.0) as u8);
} }
} }

View File

@ -1,6 +1,9 @@
use std::fs::File;
use std::io::BufWriter;
use crate::hittable::HittableList; use crate::hittable::HittableList;
use crate::ppm_writer::PPMWriter;
use crate::types_defined::{Camera, Point, Sphere, Vec3}; use crate::types_defined::{Camera, Point, Sphere, Vec3};
use write_file_util::write_image;
mod camera; mod camera;
mod color; mod color;
mod hittable; mod hittable;
@ -10,20 +13,35 @@ mod types_defined;
mod vec3; mod vec3;
mod write_file_util; mod write_file_util;
mod math_utils; mod math_utils;
mod ppm_writer;
fn main() { fn main() {
camera_render(); camera_render();
} }
fn camera_render() { fn camera_render() {
let camera = Camera::new(
400, let width: i32 = 400;
let height: i32 = 200;
let pw_r = PPMWriter::new(
BufWriter::new(File::create("./target/ray_sphere_normal_scene_render.ppm").unwrap()),
width, height);
if let Err(e) = pw_r {
println!("创建文件报错:{}", e);
return;
}
let pw = &mut pw_r.unwrap();
let mut camera: Camera = Camera::new(
width,
16.0 / 9.0, 16.0 / 9.0,
2.0, 2.0,
Point::new(0.0, 0.0, 0.0), Point::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, -1.0), Vec3::new(0.0, 0.0, -1.0),
100, 50,
50 50,
pw
); );
// world // world
// world objects(spheres) // world objects(spheres)
@ -34,9 +52,9 @@ fn camera_render() {
world.put(Box::new(Sphere::new(Point::new(0.0, -100.0, -1.0), 100.0))); world.put(Box::new(Sphere::new(Point::new(0.0, -100.0, -1.0), 100.0)));
world.put(Box::new(Sphere::new(Point::new(-0.5, 0.2, -0.5), 0.4))); world.put(Box::new(Sphere::new(Point::new(-0.5, 0.2, -0.5), 0.4)));
let ppm_content = camera.render(&world); camera.render(&world);
write_image( // write_image(
ppm_content, // ppm_content,
"./target/ray_sphere_normal_scene_render.ppm".to_string(), // "".to_string(),
) // )
} }

36
src/ppm_writer.rs Normal file
View File

@ -0,0 +1,36 @@
use std::io::{BufWriter, Write, Result};
use crate::types_defined::Color;
pub struct PPMWriter<W: Write> {
writter: BufWriter<W>
}
impl<W: Write> PPMWriter<W> {
/// 创建新的 PPM 写入器
///
/// 参数:
/// writer: 实现 Write 的目标
/// width: 图像宽度
/// height: 图像高度
pub fn new(mut inner: W, width: i32, height: i32) -> Result<Self> {
// 写入 PPM 头 (P6 二进制格式)
let header = format!("P6\n{} {}\n255\n", width, height);
inner.write_all(header.as_bytes())?;
Ok(PPMWriter { writter: BufWriter::new(inner) })
}
/// 写入单个像素 (高性能实现)
#[inline]
pub fn write(&mut self, color: Color) -> Result<()> {
// 直接写入字节数组避免额外内存分配
let bytes = [color.x as u8, color.y as u8, color.z as u8];
self.writter.write_all(&bytes)
}
/// 完成写入并刷新缓冲区
pub fn finish(mut self) -> Result<()> {
self.writter.flush()
}
}

View File

@ -1,8 +1,10 @@
use std::{fs::File, io::{BufWriter, Write}};
use crate::ppm_writer::PPMWriter;
/* /*
* [3] * [3]
*/ */
use crate::hittable::Hittable;
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Vec3 { pub struct Vec3 {
pub x: f32, pub x: f32,
@ -28,7 +30,7 @@ pub struct HitRecord {
pub front_face: bool, pub front_face: bool,
} }
pub struct Camera { pub struct Camera<'a> {
pub image_width: i32, pub image_width: i32,
pub image_height: i32, pub image_height: i32,
pub aspect_ratio: f32, pub aspect_ratio: f32,
@ -44,7 +46,10 @@ pub struct Camera {
// sample times // sample times
pub sample_times: i8, pub sample_times: i8,
pub reflect_depth: i8 pub reflect_depth: i8,
// writer
pub ppm_file_writer: &'a mut PPMWriter<BufWriter<File>>
} }
/* /*