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 error::SourceFile;
|
||||
use material::PbrtMaterial;
|
||||
use miette::{Diagnostic, IntoDiagnostic, Result, SourceSpan, bail, miette};
|
||||
use ray_tracing_core::{
|
||||
affine_transform::AffineTransform,
|
||||
|
|
@ -16,10 +17,10 @@ use thiserror::Error;
|
|||
|
||||
#[macro_use]
|
||||
mod tokenizer;
|
||||
|
||||
mod error;
|
||||
|
||||
mod material;
|
||||
mod texture;
|
||||
|
||||
struct Lexer {
|
||||
input: Tokenizer,
|
||||
}
|
||||
|
|
@ -70,6 +71,9 @@ enum Statement {
|
|||
Unknown(String, Vec<String>),
|
||||
Transform(AffineTransform),
|
||||
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> {
|
||||
|
|
@ -399,6 +403,14 @@ impl Lexer {
|
|||
texture::parse_texture(&mut self.input, textures)
|
||||
.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" => {
|
||||
Some(parse_transform(&mut self.input).map(Statement::ConcatTransform))
|
||||
}
|
||||
|
|
@ -410,7 +422,6 @@ impl Lexer {
|
|||
Ok(s) => Ok(Statement::CoordSysTransform(s)),
|
||||
Err(e) => Err(e),
|
||||
}),
|
||||
|
||||
"WorldBegin" => Some(Ok(Statement::WorldBegin)),
|
||||
_ => {
|
||||
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 miette::{Result, miette};
|
||||
use ray_tracing_core::{affine_transform::AffineTransform, color::Color, prelude::Float};
|
||||
use scale::SpectrumScaleTexture2d;
|
||||
use std::{collections::HashMap, ops::Deref, sync::Arc};
|
||||
|
||||
use crate::tokenizer::Tokenizer;
|
||||
|
||||
mod checkerboard;
|
||||
mod imagemap;
|
||||
mod scale;
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
#[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)]
|
||||
enum TextureMapping {
|
||||
UV,
|
||||
|
|
@ -46,6 +65,16 @@ fn parse_rgb(input: &mut Tokenizer) -> Result<Color> {
|
|||
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(
|
||||
input: &mut Tokenizer,
|
||||
textures: &HashMap<String, Arc<dyn PbrtTexture>>,
|
||||
|
|
@ -59,7 +88,7 @@ fn parse_spectrum_texture(
|
|||
vscale, Float, 1.0;
|
||||
udelta, Float, 0.0;
|
||||
vdelta, Float, 0.0;
|
||||
dimension, u8, 2;
|
||||
dimension, TextureDimension, TextureDimension::D2;
|
||||
tex1, ValueTexture<Color, String>, ValueTexture::Value(Color::white());
|
||||
tex2, ValueTexture<Color, String>, ValueTexture::Value(Color::black())
|
||||
=>
|
||||
|
|
@ -68,7 +97,7 @@ fn parse_spectrum_texture(
|
|||
vscale, "\"float vscale\"", input.parse_parameter()?;
|
||||
udelta, "\"float udelta\"", 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, "\"spectrum tex1\"", ValueTexture::Value(parse_spectrum(input)?);
|
||||
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);
|
||||
|
||||
match t.dimension {
|
||||
2 => Ok(Arc::new(checkerboard::SpectrumCheckerboardTexture2d {
|
||||
TextureDimension::D2 => Ok(Arc::new(checkerboard::SpectrumCheckerboardTexture2d {
|
||||
mapping,
|
||||
tex: [
|
||||
match t.tex1 {
|
||||
|
|
@ -108,7 +137,9 @@ fn parse_spectrum_texture(
|
|||
},
|
||||
],
|
||||
})),
|
||||
_ => Err(miette!("Only dimension 2 and 3 are supported")),
|
||||
TextureDimension::D3 => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
"\"imagemap\"" => {
|
||||
|
|
@ -149,6 +180,43 @@ fn parse_spectrum_texture(
|
|||
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}")),
|
||||
}
|
||||
}
|
||||
|
|
@ -162,6 +230,7 @@ pub fn parse_texture(
|
|||
|
||||
match texture_type.as_str() {
|
||||
"\"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")),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ impl PbrtTexture for FloatCheckerboardTexture2d {
|
|||
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"))
|
||||
}
|
||||
|
||||
fn get_dimension(&self) -> TextureDimension {
|
||||
TextureDimension::D2
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
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>> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn get_dimension(&self) -> TextureDimension {
|
||||
TextureDimension::D2
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ impl ImageMapEncoding {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct SpectrumImageMapTexture {
|
||||
mapping: UVMapping,
|
||||
scale: Float,
|
||||
|
|
@ -55,6 +54,18 @@ pub(super) struct SpectrumImageMapTexture {
|
|||
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 {
|
||||
if x <= 0.04045 {
|
||||
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>> {
|
||||
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