Implement initial area light
This commit is contained in:
parent
95092b1571
commit
333acab099
3 changed files with 102 additions and 22 deletions
|
|
@ -17,6 +17,20 @@ impl<A, B> Either<A, B> {
|
||||||
Either::B(b) => Either::B(f(b)),
|
Either::B(b) => Either::B(f(b)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_a(&self) -> Option<&A> {
|
||||||
|
match self {
|
||||||
|
Either::A(a) => Some(a),
|
||||||
|
Either::B(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_b(&self) -> Option<&B> {
|
||||||
|
match self {
|
||||||
|
Either::A(_) => None,
|
||||||
|
Either::B(b) => Some(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, E> Either<A, Result<B, E>> {
|
impl<A, B, E> Either<A, Result<B, E>> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
either::Either,
|
||||||
scene::PbrtScene,
|
scene::PbrtScene,
|
||||||
shape::{Shape, ShapeAlpha, ShapeType},
|
shape::{Shape, ShapeAlpha, ShapeType},
|
||||||
tokenizer::{Token, Tokenizer},
|
tokenizer::{Token, Tokenizer},
|
||||||
|
|
@ -8,6 +9,7 @@ use miette::{IntoDiagnostic, Result, bail, miette};
|
||||||
use ray_tracing_core::{
|
use ray_tracing_core::{
|
||||||
affine_transform::AffineTransform,
|
affine_transform::AffineTransform,
|
||||||
color::Color,
|
color::Color,
|
||||||
|
light::Light,
|
||||||
math::{Dir3, Pos3},
|
math::{Dir3, Pos3},
|
||||||
prelude::{Float, Rng},
|
prelude::{Float, Rng},
|
||||||
};
|
};
|
||||||
|
|
@ -83,6 +85,22 @@ enum Statement<R> {
|
||||||
Material(Arc<dyn PbrtMaterial<R>>),
|
Material(Arc<dyn PbrtMaterial<R>>),
|
||||||
MakeNamedMaterial(String, Arc<dyn PbrtMaterial<R>>),
|
MakeNamedMaterial(String, Arc<dyn PbrtMaterial<R>>),
|
||||||
NamedMaterial(String),
|
NamedMaterial(String),
|
||||||
|
AreaLight(AreaLight),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AreaLight {
|
||||||
|
pub color: Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: Rng> Light<R> for AreaLight {
|
||||||
|
fn emit(&self, w_in: Dir3, _rng: &mut R) -> Color {
|
||||||
|
if w_in.y() > 0.0 {
|
||||||
|
self.color
|
||||||
|
} else {
|
||||||
|
Color::black()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_look_at<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
|
fn parse_look_at<R>(iter: &mut Tokenizer) -> Result<Statement<R>> {
|
||||||
|
|
@ -417,7 +435,9 @@ impl Lexer {
|
||||||
material::parse_make_named_material(&mut self.input, context)
|
material::parse_make_named_material(&mut self.input, context)
|
||||||
.map(|(name, material)| Statement::MakeNamedMaterial(name, material)),
|
.map(|(name, material)| Statement::MakeNamedMaterial(name, material)),
|
||||||
),
|
),
|
||||||
"NamedMaterial" => Some(self.input.parse_parameter().map(Statement::NamedMaterial)),
|
"NamedMaterial" => {
|
||||||
|
Some(self.input.next_string_value().map(Statement::NamedMaterial))
|
||||||
|
}
|
||||||
"ConcatTransform" => {
|
"ConcatTransform" => {
|
||||||
Some(parse_transform(&mut self.input).map(Statement::ConcatTransform))
|
Some(parse_transform(&mut self.input).map(Statement::ConcatTransform))
|
||||||
}
|
}
|
||||||
|
|
@ -429,6 +449,8 @@ impl Lexer {
|
||||||
Ok(s) => Ok(Statement::CoordSysTransform(s)),
|
Ok(s) => Ok(Statement::CoordSysTransform(s)),
|
||||||
Err(e) => Err(e),
|
Err(e) => Err(e),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
"AreaLightSource" => Some(parse_area_light(&mut self.input)),
|
||||||
"WorldBegin" => Some(Ok(Statement::WorldBegin)),
|
"WorldBegin" => Some(Ok(Statement::WorldBegin)),
|
||||||
_ => {
|
_ => {
|
||||||
if s.chars().any(|c| !c.is_ascii_alphabetic()) {
|
if s.chars().any(|c| !c.is_ascii_alphabetic()) {
|
||||||
|
|
@ -459,6 +481,22 @@ impl Lexer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_area_light<R>(input: &mut Tokenizer) -> Result<Statement<R>> {
|
||||||
|
let s = input.next_string_value()?;
|
||||||
|
|
||||||
|
if s.as_str() != "diffuse" {
|
||||||
|
return Err(miette!(
|
||||||
|
labels = vec![input.last_span_labeled(Some("here"))],
|
||||||
|
"Only diffuse area light supported."
|
||||||
|
)
|
||||||
|
.with_source_code(input.get_src()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Statement::AreaLight(parse_dict2!(input, AreaLight;
|
||||||
|
color, Color::white(), ["rgb L", texture::parse_rgb(input)?]
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_transform(input: &mut Tokenizer) -> Result<AffineTransform> {
|
fn parse_transform(input: &mut Tokenizer) -> Result<AffineTransform> {
|
||||||
input.next_expect_bracket_open()?;
|
input.next_expect_bracket_open()?;
|
||||||
let mut v = [0.0; 16];
|
let mut v = [0.0; 16];
|
||||||
|
|
@ -615,6 +653,7 @@ pub struct PbrtContext<R> {
|
||||||
ctm: Vec<AffineTransform>,
|
ctm: Vec<AffineTransform>,
|
||||||
textures: HashMap<String, Arc<dyn PbrtTexture>>,
|
textures: HashMap<String, Arc<dyn PbrtTexture>>,
|
||||||
material: Vec<Arc<dyn PbrtMaterial<R>>>,
|
material: Vec<Arc<dyn PbrtMaterial<R>>>,
|
||||||
|
area_light: Vec<AreaLight>,
|
||||||
materials: HashMap<String, Arc<dyn PbrtMaterial<R>>>,
|
materials: HashMap<String, Arc<dyn PbrtMaterial<R>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -623,6 +662,7 @@ impl<R> PbrtContext<R> {
|
||||||
Self {
|
Self {
|
||||||
ctm: vec![AffineTransform::identity()],
|
ctm: vec![AffineTransform::identity()],
|
||||||
textures: HashMap::new(),
|
textures: HashMap::new(),
|
||||||
|
area_light: Vec::new(),
|
||||||
material: Vec::new(),
|
material: Vec::new(),
|
||||||
materials: HashMap::new(),
|
materials: HashMap::new(),
|
||||||
}
|
}
|
||||||
|
|
@ -651,6 +691,11 @@ impl<R> PbrtContext<R> {
|
||||||
self.material
|
self.material
|
||||||
.push(Arc::clone(self.material.last().unwrap()));
|
.push(Arc::clone(self.material.last().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.area_light.is_empty() {
|
||||||
|
self.area_light
|
||||||
|
.push(self.area_light.last().unwrap().clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> Result<()> {
|
fn pop(&mut self) -> Result<()> {
|
||||||
|
|
@ -661,6 +706,7 @@ impl<R> PbrtContext<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.material.pop();
|
self.material.pop();
|
||||||
|
self.area_light.pop();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -747,17 +793,26 @@ fn inner_parse_pbrt<R: Rng + std::fmt::Debug>(
|
||||||
}
|
}
|
||||||
Statement::Shape(shape_type, shape_alpha) => {
|
Statement::Shape(shape_type, shape_alpha) => {
|
||||||
dbg!(&context);
|
dbg!(&context);
|
||||||
pbrt.scene.shapes.push(Shape {
|
if context.area_light.is_empty() {
|
||||||
ctm: context.get_ctm(),
|
pbrt.scene.shapes.push(Shape {
|
||||||
material: Arc::clone(
|
ctm: context.get_ctm(),
|
||||||
context
|
material: Either::A(Arc::clone(
|
||||||
.material
|
context
|
||||||
.last()
|
.material
|
||||||
.ok_or_else(|| miette!("No material specified"))?,
|
.last()
|
||||||
),
|
.ok_or_else(|| miette!("No material specified"))?,
|
||||||
obj: shape_type,
|
)),
|
||||||
alpha: shape_alpha,
|
obj: shape_type,
|
||||||
});
|
alpha: shape_alpha,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pbrt.scene.shapes.push(Shape {
|
||||||
|
ctm: context.get_ctm(),
|
||||||
|
material: Either::B(context.area_light.last().unwrap().clone()),
|
||||||
|
obj: shape_type,
|
||||||
|
alpha: shape_alpha,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Statement::CoordinateSystem(s) => {
|
Statement::CoordinateSystem(s) => {
|
||||||
named_transforms.insert(s, context.get_ctm());
|
named_transforms.insert(s, context.get_ctm());
|
||||||
|
|
@ -774,6 +829,13 @@ fn inner_parse_pbrt<R: Rng + std::fmt::Debug>(
|
||||||
*context.material.last_mut().unwrap() = m;
|
*context.material.last_mut().unwrap() = m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Statement::AreaLight(l) => {
|
||||||
|
if context.area_light.is_empty() {
|
||||||
|
context.area_light.push(l);
|
||||||
|
} else {
|
||||||
|
*context.area_light.last_mut().unwrap() = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
Statement::MakeNamedMaterial(n, m) => {
|
Statement::MakeNamedMaterial(n, m) => {
|
||||||
context.materials.insert(n, m);
|
context.materials.insert(n, m);
|
||||||
}
|
}
|
||||||
|
|
@ -801,7 +863,7 @@ fn inner_parse_pbrt<R: Rng + std::fmt::Debug>(
|
||||||
|
|
||||||
// dbg!(context);
|
// dbg!(context);
|
||||||
|
|
||||||
Ok(pbrt)
|
Ok(dbg!(pbrt))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_pbrt_v4<R: Rng + std::fmt::Debug>(
|
pub fn parse_pbrt_v4<R: Rng + std::fmt::Debug>(
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use ray_tracing_core::{affine_transform::AffineTransform, prelude::*, scene::Intersection};
|
use ray_tracing_core::{affine_transform::AffineTransform, prelude::*, scene::Intersection};
|
||||||
|
|
||||||
use crate::{material::PbrtMaterial, scene::UVMaterial};
|
use crate::{AreaLight, either::Either, material::PbrtMaterial, scene::UVMaterial};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) struct Shape<R: Rng> {
|
pub(crate) struct Shape<R: Rng> {
|
||||||
pub(crate) ctm: AffineTransform,
|
pub(crate) ctm: AffineTransform,
|
||||||
pub(crate) material: Arc<dyn PbrtMaterial<R>>,
|
pub(crate) material: Either<Arc<dyn PbrtMaterial<R>>, AreaLight>,
|
||||||
pub(crate) obj: ShapeType,
|
pub(crate) obj: ShapeType,
|
||||||
pub(crate) alpha: ShapeAlpha,
|
pub(crate) alpha: ShapeAlpha,
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ pub(crate) enum ShapeAlpha {
|
||||||
Texture(String),
|
Texture(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
// #[derive(Debug)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) enum ShapeType {
|
pub(crate) enum ShapeType {
|
||||||
Sphere {
|
Sphere {
|
||||||
|
|
@ -219,12 +219,14 @@ impl<R: Rng + std::fmt::Debug> Shape<R> {
|
||||||
t,
|
t,
|
||||||
self.ctm
|
self.ctm
|
||||||
.inverse_transform_normal((ray.at(t).as_dir()).normalize()),
|
.inverse_transform_normal((ray.at(t).as_dir()).normalize()),
|
||||||
Some(UVMaterial {
|
self.material.get_a().map(|m| UVMaterial {
|
||||||
u: phi,
|
u: phi,
|
||||||
v: Float::acos(p.z() / radius),
|
v: Float::acos(p.z() / radius),
|
||||||
material: self.material.as_ref(),
|
material: m.as_ref(),
|
||||||
}),
|
}),
|
||||||
None,
|
self.material
|
||||||
|
.get_b()
|
||||||
|
.map(|l| l as &dyn ray_tracing_core::light::Light<R>),
|
||||||
0.0,
|
0.0,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
@ -244,12 +246,14 @@ impl<R: Rng + std::fmt::Debug> Shape<R> {
|
||||||
return Some(Intersection::new(
|
return Some(Intersection::new(
|
||||||
t,
|
t,
|
||||||
Dir3::new(0.0, 0.0, 1.0),
|
Dir3::new(0.0, 0.0, 1.0),
|
||||||
Some(UVMaterial {
|
self.material.get_a().map(|m| UVMaterial {
|
||||||
u,
|
u,
|
||||||
v,
|
v,
|
||||||
material: self.material.as_ref(),
|
material: m.as_ref(),
|
||||||
}),
|
}),
|
||||||
None,
|
self.material
|
||||||
|
.get_b()
|
||||||
|
.map(|l| l as &dyn ray_tracing_core::light::Light<R>),
|
||||||
0.0,
|
0.0,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue