perf: writer
This commit is contained in:
parent
71ae83d205
commit
f60a06d84b
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
38
src/main.rs
38
src/main.rs
|
@ -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(),
|
||||||
)
|
// )
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue