rtiow: implement EnvMap in parser.

This commit is contained in:
Bill Thiede 2023-02-15 15:46:23 -08:00
parent 6fbdb49ce1
commit 5f0e7a26dd
3 changed files with 53 additions and 29 deletions

View File

@ -8,7 +8,8 @@ use crate::{
texture::{EnvMap, Texture}, texture::{EnvMap, Texture},
}; };
use serde::Deserialize; use serde::Deserialize;
use std::path::PathBuf;
use thiserror::Error;
use vec3::Vec3; use vec3::Vec3;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -16,38 +17,40 @@ pub struct Config {
scene: SceneConfig, scene: SceneConfig,
camera: CameraConfig, camera: CameraConfig,
spheres: Vec<SphereConfig>, spheres: Vec<SphereConfig>,
envmap: Option<EnvMapConfig>,
} }
impl From<Config> for Scene { #[derive(Error, Debug)]
fn from(c: Config) -> Scene { pub enum ConfigError {
#[error("failed to load image")]
ImageError(#[from] image::ImageError),
}
impl TryFrom<Config> for Scene {
type Error = ConfigError;
fn try_from(c: Config) -> Result<Scene, Self::Error> {
// TODO(wathiede): make this something that is loaded from the config and referenced by
// name in the object's config.
let material = Lambertian::new([1., 0., 0.]); let material = Lambertian::new([1., 0., 0.]);
let objects: Vec<Box<dyn Hit>> = c
let spheres: Vec<Box<dyn Hit>> = c
.spheres .spheres
.iter() .iter()
.map(|sc| -> Box<dyn Hit> { .map(|sc| -> Box<dyn Hit> {
Box::new(Sphere::new(sc.center, sc.radius, material.clone())) Box::new(Sphere::new(sc.center, sc.radius, material.clone()))
}) })
.collect(); .collect();
let world: Box<dyn Hit> = Box::new(HitableList::new(objects));
let env_map: Option<EnvMap> = None;
let lookfrom = Vec3::new(0., 80., 80.); let world: Box<dyn Hit> = Box::new(HitableList::new(spheres));
let lookat = Vec3::new(0., 0., 0.); let mut env_map: Option<EnvMap> = None;
let dist_to_focus = 10.0;
let aperture = 0.0; if let Some(em) = c.envmap {
let time_min = 0.; let im = image::open(em.path)?.into_rgb();
let time_max = 1.; env_map = Some(EnvMap::new(im));
let camera = Camera::new( };
lookfrom,
lookat, let camera = make_camera(&c.camera, c.scene.width, c.scene.height);
Vec3::new(0., 1., 0.),
45.,
c.scene.width as f32 / c.scene.height as f32,
aperture,
dist_to_focus,
time_min,
time_max,
);
let scene = Scene { let scene = Scene {
world, world,
@ -60,11 +63,24 @@ impl From<Config> for Scene {
height: c.scene.height, height: c.scene.height,
global_illumination: c.scene.global_illumination.unwrap_or(true), global_illumination: c.scene.global_illumination.unwrap_or(true),
}; };
dbg!(&scene); Ok(scene)
scene
} }
} }
fn make_camera(cfg: &CameraConfig, width: usize, height: usize) -> Camera {
Camera::new(
cfg.lookfrom.into(),
cfg.lookat.into(),
Vec3::new(0., 1., 0.),
cfg.fov,
width as f32 / height as f32,
cfg.aperture,
cfg.focus_dist,
cfg.time_min,
cfg.time_max,
)
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
struct SceneConfig { struct SceneConfig {
subsamples: Option<usize>, subsamples: Option<usize>,
@ -92,3 +108,8 @@ pub struct CameraConfig {
time_min: f32, time_min: f32,
time_max: f32, time_max: f32,
} }
#[derive(Debug, Deserialize)]
struct EnvMapConfig {
path: PathBuf,
}

View File

@ -1,12 +1,12 @@
[scene] [scene]
width = 768 width = 768
height = 768 height = 768
subsamples = 1000 #subsamples = 1000
[camera] [camera]
lookfrom = [0.0, 10.0, 0.0] lookfrom = [0.0, 10.0, -100.0]
lookat = [0.0, 0.0, 0.0] lookat = [0.0, 0.0, 0.0]
fov = 45.0 fov = 45
aspect = 1 aspect = 1
aperture = 0.0 aperture = 0.0
focus_dist = 10.0 focus_dist = 10.0
@ -22,3 +22,6 @@ radius = 10
[[spheres]] [[spheres]]
center = [-30.0, 0.0, 0.0] center = [-30.0, 0.0, 0.0]
radius = 10 radius = 10
[envmap]
path = "/home/wathiede/src/xinu.tv/raytracers/rtiow/renderer/images/52681723945_e1d94d3df9_6k.jpg"

View File

@ -65,7 +65,7 @@ fn main() -> Result<()> {
let s = std::fs::read_to_string(config)?; let s = std::fs::read_to_string(config)?;
let cfg: Config = toml::from_str(&s)?; let cfg: Config = toml::from_str(&s)?;
println!("{:#?}", cfg); println!("{:#?}", cfg);
cfg.into() cfg.try_into()?
} }
_ => unreachable!(), _ => unreachable!(),
}; };