Add Pbrt scale texture and initial material stuff
This commit is contained in:
		
							parent
							
								
									2476d2d49a
								
							
						
					
					
						commit
						0dfa2128dd
					
				
					 6 changed files with 176 additions and 8 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| use crate::tokenizer::Tokenizer; | use crate::tokenizer::Tokenizer; | ||||||
| use error::SourceFile; | use error::SourceFile; | ||||||
|  | use material::PbrtMaterial; | ||||||
| use miette::{Diagnostic, IntoDiagnostic, Result, SourceSpan, bail, miette}; | use miette::{Diagnostic, IntoDiagnostic, Result, SourceSpan, bail, miette}; | ||||||
| use ray_tracing_core::{ | use ray_tracing_core::{ | ||||||
|     affine_transform::AffineTransform, |     affine_transform::AffineTransform, | ||||||
|  | @ -16,10 +17,10 @@ use thiserror::Error; | ||||||
| 
 | 
 | ||||||
| #[macro_use] | #[macro_use] | ||||||
| mod tokenizer; | mod tokenizer; | ||||||
| 
 |  | ||||||
| mod error; | mod error; | ||||||
| 
 | mod material; | ||||||
| mod texture; | mod texture; | ||||||
|  | 
 | ||||||
| struct Lexer { | struct Lexer { | ||||||
|     input: Tokenizer, |     input: Tokenizer, | ||||||
| } | } | ||||||
|  | @ -70,6 +71,9 @@ enum Statement { | ||||||
|     Unknown(String, Vec<String>), |     Unknown(String, Vec<String>), | ||||||
|     Transform(AffineTransform), |     Transform(AffineTransform), | ||||||
|     Texture(String, Arc<dyn PbrtTexture>), |     Texture(String, Arc<dyn PbrtTexture>), | ||||||
|  |     Material(Arc<dyn PbrtMaterial>), | ||||||
|  |     MakeNamedMaterial(String, Arc<dyn PbrtMaterial>), | ||||||
|  |     NamedMaterial(String), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> { | fn parse_look_at(iter: &mut Tokenizer) -> Result<Statement> { | ||||||
|  | @ -399,6 +403,14 @@ impl Lexer { | ||||||
|                     texture::parse_texture(&mut self.input, textures) |                     texture::parse_texture(&mut self.input, textures) | ||||||
|                         .map(|(name, texture)| Statement::Texture(name, texture)), |                         .map(|(name, texture)| Statement::Texture(name, texture)), | ||||||
|                 ), |                 ), | ||||||
|  |                 "Material" => Some( | ||||||
|  |                     material::parse_material(&mut self.input, textures).map(Statement::Material), | ||||||
|  |                 ), | ||||||
|  |                 "MakeNamedMaterial" => Some( | ||||||
|  |                     material::parse_make_named_material(&mut self.input, textures) | ||||||
|  |                         .map(|(name, material)| Statement::MakeNamedMaterial(name, material)), | ||||||
|  |                 ), | ||||||
|  |                 "NamedMaterial" => Some(self.input.parse_parameter().map(Statement::NamedMaterial)), | ||||||
|                 "ConcatTransform" => { |                 "ConcatTransform" => { | ||||||
|                     Some(parse_transform(&mut self.input).map(Statement::ConcatTransform)) |                     Some(parse_transform(&mut self.input).map(Statement::ConcatTransform)) | ||||||
|                 } |                 } | ||||||
|  | @ -410,7 +422,6 @@ impl Lexer { | ||||||
|                     Ok(s) => Ok(Statement::CoordSysTransform(s)), |                     Ok(s) => Ok(Statement::CoordSysTransform(s)), | ||||||
|                     Err(e) => Err(e), |                     Err(e) => Err(e), | ||||||
|                 }), |                 }), | ||||||
| 
 |  | ||||||
|                 "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()) { | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								ray-tracing-pbrt-scene/src/material.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ray-tracing-pbrt-scene/src/material.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | use super::*; | ||||||
|  | 
 | ||||||
|  | pub trait PbrtMaterial: std::fmt::Debug + Send + Sync {} | ||||||
|  | 
 | ||||||
|  | pub fn parse_make_named_material( | ||||||
|  |     input: &mut Tokenizer, | ||||||
|  |     textures: &HashMap<String, Arc<dyn PbrtTexture>>, | ||||||
|  | ) -> Result<(String, Arc<dyn PbrtMaterial>)> { | ||||||
|  |     let name = input.parse_next()?; | ||||||
|  | 
 | ||||||
|  |     if input.parse_next::<String>()?.as_str() != "\"string type\"" { | ||||||
|  |         return Err(miette!( | ||||||
|  |             "first element of make named material dict has to be type" | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |     Ok((name, parse_material(input, textures)?)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn parse_material( | ||||||
|  |     input: &mut Tokenizer, | ||||||
|  |     textures: &HashMap<String, Arc<dyn PbrtTexture>>, | ||||||
|  | ) -> Result<Arc<dyn PbrtMaterial>> { | ||||||
|  |     let material: String = input.parse_parameter()?; | ||||||
|  | 
 | ||||||
|  |     dbg!(material); | ||||||
|  | 
 | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | @ -1,14 +1,17 @@ | ||||||
| use imagemap::{ImageMapEncoding, ImageMapWrap, SpectrumImageMapTexture}; | use imagemap::{ImageMapEncoding, ImageMapWrap, SpectrumImageMapTexture}; | ||||||
| use miette::{Result, miette}; | use miette::{Result, miette}; | ||||||
| use ray_tracing_core::{affine_transform::AffineTransform, color::Color, prelude::Float}; | use ray_tracing_core::{affine_transform::AffineTransform, color::Color, prelude::Float}; | ||||||
|  | use scale::SpectrumScaleTexture2d; | ||||||
| use std::{collections::HashMap, ops::Deref, sync::Arc}; | use std::{collections::HashMap, ops::Deref, sync::Arc}; | ||||||
| 
 | 
 | ||||||
| use crate::tokenizer::Tokenizer; | use crate::tokenizer::Tokenizer; | ||||||
| 
 | 
 | ||||||
| mod checkerboard; | mod checkerboard; | ||||||
| mod imagemap; | mod imagemap; | ||||||
|  | mod scale; | ||||||
| 
 | 
 | ||||||
| pub trait PbrtTexture: std::fmt::Debug + Send + Sync { | pub trait PbrtTexture: std::fmt::Debug + Send + Sync { | ||||||
|  |     fn get_dimension(&self) -> TextureDimension; | ||||||
|     fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_float_texture>>; |     fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_float_texture>>; | ||||||
|     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>>; |     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>>; | ||||||
| } | } | ||||||
|  | @ -21,6 +24,22 @@ pub trait Pbrt_2d_spectrum_texture: std::fmt::Debug + Sync + Send { | ||||||
|     fn get(&self, u: Float, v: Float) -> Color; |     fn get(&self, u: Float, v: Float) -> Color; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | enum TextureDimension { | ||||||
|  |     D2, | ||||||
|  |     D3, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TextureDimension { | ||||||
|  |     fn new(x: String) -> Result<Self> { | ||||||
|  |         match x.as_str() { | ||||||
|  |             "2" => Ok(TextureDimension::D2), | ||||||
|  |             "3" => Ok(TextureDimension::D3), | ||||||
|  |             _ => Err(miette!("Error parsing Texture dimension")), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| enum TextureMapping { | enum TextureMapping { | ||||||
|     UV, |     UV, | ||||||
|  | @ -46,6 +65,16 @@ fn parse_rgb(input: &mut Tokenizer) -> Result<Color> { | ||||||
|     Ok(Color::new(t[0], t[1], t[2])) |     Ok(Color::new(t[0], t[1], t[2])) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn parse_float_texture( | ||||||
|  |     input: &mut Tokenizer, | ||||||
|  |     textures: &HashMap<String, Arc<dyn PbrtTexture>>, | ||||||
|  | ) -> Result<Arc<dyn PbrtTexture>> { | ||||||
|  |     let texture_class: String = input.parse_next()?; | ||||||
|  | 
 | ||||||
|  |     dbg!(texture_class); | ||||||
|  |     todo!() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn parse_spectrum_texture( | fn parse_spectrum_texture( | ||||||
|     input: &mut Tokenizer, |     input: &mut Tokenizer, | ||||||
|     textures: &HashMap<String, Arc<dyn PbrtTexture>>, |     textures: &HashMap<String, Arc<dyn PbrtTexture>>, | ||||||
|  | @ -59,7 +88,7 @@ fn parse_spectrum_texture( | ||||||
|                 vscale, Float, 1.0; |                 vscale, Float, 1.0; | ||||||
|                 udelta, Float, 0.0; |                 udelta, Float, 0.0; | ||||||
|                 vdelta, Float, 0.0; |                 vdelta, Float, 0.0; | ||||||
|                 dimension, u8, 2; |                 dimension, TextureDimension, TextureDimension::D2; | ||||||
|                 tex1, ValueTexture<Color, String>, ValueTexture::Value(Color::white()); |                 tex1, ValueTexture<Color, String>, ValueTexture::Value(Color::white()); | ||||||
|                 tex2, ValueTexture<Color, String>, ValueTexture::Value(Color::black()) |                 tex2, ValueTexture<Color, String>, ValueTexture::Value(Color::black()) | ||||||
|                 => |                 => | ||||||
|  | @ -68,7 +97,7 @@ fn parse_spectrum_texture( | ||||||
|                 vscale, "\"float vscale\"", input.parse_parameter()?; |                 vscale, "\"float vscale\"", input.parse_parameter()?; | ||||||
|                 udelta, "\"float udelta\"", input.parse_parameter()?; |                 udelta, "\"float udelta\"", input.parse_parameter()?; | ||||||
|                 vdelta, "\"float vdelta\"", input.parse_parameter()?; |                 vdelta, "\"float vdelta\"", input.parse_parameter()?; | ||||||
|                 dimension, "\"integer dimension\"", input.parse_parameter()?; |                 dimension, "\"integer dimension\"", TextureDimension::new(input.parse_parameter()?)?; | ||||||
|                 tex1, "\"rgb tex1\"", ValueTexture::Value(parse_rgb(input)?); |                 tex1, "\"rgb tex1\"", ValueTexture::Value(parse_rgb(input)?); | ||||||
|                 tex1, "\"spectrum tex1\"", ValueTexture::Value(parse_spectrum(input)?); |                 tex1, "\"spectrum tex1\"", ValueTexture::Value(parse_spectrum(input)?); | ||||||
|                 tex1, "\"texture tex1\"", ValueTexture::Texture(input.parse_parameter()?); |                 tex1, "\"texture tex1\"", ValueTexture::Texture(input.parse_parameter()?); | ||||||
|  | @ -81,7 +110,7 @@ fn parse_spectrum_texture( | ||||||
|             let mapping = UVMapping::new(t.mapping, t.uscale, t.vscale, t.udelta, t.vdelta); |             let mapping = UVMapping::new(t.mapping, t.uscale, t.vscale, t.udelta, t.vdelta); | ||||||
| 
 | 
 | ||||||
|             match t.dimension { |             match t.dimension { | ||||||
|                 2 => Ok(Arc::new(checkerboard::SpectrumCheckerboardTexture2d { |                 TextureDimension::D2 => Ok(Arc::new(checkerboard::SpectrumCheckerboardTexture2d { | ||||||
|                     mapping, |                     mapping, | ||||||
|                     tex: [ |                     tex: [ | ||||||
|                         match t.tex1 { |                         match t.tex1 { | ||||||
|  | @ -108,7 +137,9 @@ fn parse_spectrum_texture( | ||||||
|                         }, |                         }, | ||||||
|                     ], |                     ], | ||||||
|                 })), |                 })), | ||||||
|                 _ => Err(miette!("Only dimension 2 and 3 are supported")), |                 TextureDimension::D3 => { | ||||||
|  |                     todo!() | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         "\"imagemap\"" => { |         "\"imagemap\"" => { | ||||||
|  | @ -149,6 +180,43 @@ fn parse_spectrum_texture( | ||||||
|                 dbg!(path), |                 dbg!(path), | ||||||
|             )?)) |             )?)) | ||||||
|         } |         } | ||||||
|  |         "\"scale\"" => { | ||||||
|  |             let t = parse_dict!(input => | ||||||
|  |                 tex, ValueTexture<Color, String>, ValueTexture::Value(Color::white()); | ||||||
|  |                 scale, ValueTexture<Float, String>, ValueTexture::Value(1.0) | ||||||
|  |                 => | ||||||
|  |                 tex, "\"rgb tex\"", ValueTexture::Value(parse_rgb(input)?); | ||||||
|  |                 tex, "\"spectrum tex\"", ValueTexture::Value(parse_spectrum(input)?); | ||||||
|  |                 tex, "\"texture tex\"", ValueTexture::Texture(input.parse_parameter()?); | ||||||
|  |                 scale, "\"float scale\"", ValueTexture::Value(input.parse_parameter()?); | ||||||
|  |                 scale, "\"texture scale\"", ValueTexture::Texture(input.parse_parameter()?) | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             Ok(Arc::new(SpectrumScaleTexture2d { | ||||||
|  |                 tex: match t.tex { | ||||||
|  |                     ValueTexture::Value(v) => ValueTexture::Value(v), | ||||||
|  |                     ValueTexture::Texture(t) => ValueTexture::Texture( | ||||||
|  |                         Arc::clone( | ||||||
|  |                             textures | ||||||
|  |                                 .get(&t) | ||||||
|  |                                 .ok_or_else(|| miette!("Unable to find texture scale"))?, | ||||||
|  |                         ) | ||||||
|  |                         .get_2d_spectrum_texture()?, | ||||||
|  |                     ), | ||||||
|  |                 }, | ||||||
|  |                 scale: match t.scale { | ||||||
|  |                     ValueTexture::Value(v) => ValueTexture::Value(v), | ||||||
|  |                     ValueTexture::Texture(t) => ValueTexture::Texture( | ||||||
|  |                         Arc::clone( | ||||||
|  |                             textures | ||||||
|  |                                 .get(&t) | ||||||
|  |                                 .ok_or_else(|| miette!("Unable to find texture scale"))?, | ||||||
|  |                         ) | ||||||
|  |                         .get_2d_float_texture()?, | ||||||
|  |                     ), | ||||||
|  |                 }, | ||||||
|  |             })) | ||||||
|  |         } | ||||||
|         _ => Err(miette!("unknown error {texture_class}")), |         _ => Err(miette!("unknown error {texture_class}")), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -162,6 +230,7 @@ pub fn parse_texture( | ||||||
| 
 | 
 | ||||||
|     match texture_type.as_str() { |     match texture_type.as_str() { | ||||||
|         "\"spectrum\"" => parse_spectrum_texture(input, textures).map(|t| (texture_name, t)), |         "\"spectrum\"" => parse_spectrum_texture(input, textures).map(|t| (texture_name, t)), | ||||||
|  |         "\"float\"" => parse_float_texture(input, textures).map(|t| (texture_name, t)), | ||||||
|         _ => Err(miette!("Texture type has to be spectrum or float")), |         _ => Err(miette!("Texture type has to be spectrum or float")), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -35,6 +35,10 @@ impl PbrtTexture for FloatCheckerboardTexture2d { | ||||||
|     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { |     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { | ||||||
|         Err(miette!("Unable to use this texture as a spectrum texture")) |         Err(miette!("Unable to use this texture as a spectrum texture")) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn get_dimension(&self) -> TextureDimension { | ||||||
|  |         TextureDimension::D2 | ||||||
|  |     } | ||||||
| } | } | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub(super) struct SpectrumCheckerboardTexture2d { | pub(super) struct SpectrumCheckerboardTexture2d { | ||||||
|  | @ -71,4 +75,8 @@ impl PbrtTexture for SpectrumCheckerboardTexture2d { | ||||||
|     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { |     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { | ||||||
|         Ok(self) |         Ok(self) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn get_dimension(&self) -> TextureDimension { | ||||||
|  |         TextureDimension::D2 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,7 +46,6 @@ impl ImageMapEncoding { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub(super) struct SpectrumImageMapTexture { | pub(super) struct SpectrumImageMapTexture { | ||||||
|     mapping: UVMapping, |     mapping: UVMapping, | ||||||
|     scale: Float, |     scale: Float, | ||||||
|  | @ -55,6 +54,18 @@ pub(super) struct SpectrumImageMapTexture { | ||||||
|     image: image::Rgb32FImage, |     image: image::Rgb32FImage, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl std::fmt::Debug for SpectrumImageMapTexture { | ||||||
|  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         f.debug_struct("SpectrumImageMapTexture") | ||||||
|  |             .field("mapping", &self.mapping) | ||||||
|  |             .field("scale", &self.scale) | ||||||
|  |             .field("wrap", &self.wrap) | ||||||
|  |             .field("invert", &self.invert) | ||||||
|  |             .field("image", &"image data") | ||||||
|  |             .finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn srgb_nonlinear(x: f32) -> f32 { | fn srgb_nonlinear(x: f32) -> f32 { | ||||||
|     if x <= 0.04045 { |     if x <= 0.04045 { | ||||||
|         x / 12.92 |         x / 12.92 | ||||||
|  | @ -125,4 +136,8 @@ impl PbrtTexture for SpectrumImageMapTexture { | ||||||
|     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { |     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { | ||||||
|         Ok(self) |         Ok(self) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn get_dimension(&self) -> TextureDimension { | ||||||
|  |         TextureDimension::D2 | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								ray-tracing-pbrt-scene/src/texture/scale.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								ray-tracing-pbrt-scene/src/texture/scale.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | use super::*; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub(super) struct SpectrumScaleTexture2d { | ||||||
|  |     pub(super) tex: ValueTexture<Color, Arc<dyn Pbrt_2d_spectrum_texture>>, | ||||||
|  |     pub(super) scale: ValueTexture<Float, Arc<dyn Pbrt_2d_float_texture>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PbrtTexture for SpectrumScaleTexture2d { | ||||||
|  |     fn get_dimension(&self) -> TextureDimension { | ||||||
|  |         TextureDimension::D2 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_2d_float_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_float_texture>> { | ||||||
|  |         Err(miette!("Unable to convert to float texture")) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn get_2d_spectrum_texture(self: Arc<Self>) -> Result<Arc<dyn Pbrt_2d_spectrum_texture>> { | ||||||
|  |         Ok(self) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Pbrt_2d_spectrum_texture for SpectrumScaleTexture2d { | ||||||
|  |     fn get(&self, u: Float, v: Float) -> Color { | ||||||
|  |         let x = match &self.tex { | ||||||
|  |             ValueTexture::Value(x) => *x, | ||||||
|  |             ValueTexture::Texture(t) => t.get(u, v), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let s = match &self.scale { | ||||||
|  |             ValueTexture::Value(s) => *s, | ||||||
|  |             ValueTexture::Texture(t) => t.get(u, v), | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         x * s | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue