Continuing the slog
This commit is contained in:
parent
2e9526ce18
commit
7c35f9b180
8 changed files with 201 additions and 98 deletions
|
|
@ -96,13 +96,13 @@ impl MaterialTrait for ThinDielectricMaterial {
|
|||
ctx: &MaterialEvalContext,
|
||||
lambda: &mut SampledWavelengths,
|
||||
) -> BSDF {
|
||||
let sampled_eta = self.eta.evaluate(lambda[0]);
|
||||
let mut sampled_eta = self.eta.evaluate(lambda[0]);
|
||||
if !self.eta.is_constant() {
|
||||
lambda.terminate_secondary_inplace();
|
||||
}
|
||||
|
||||
if sampled_eta == 0. {
|
||||
sampled_eta == 1.;
|
||||
sampled_eta = 1.;
|
||||
}
|
||||
|
||||
let bxdf = BxDF::ThinDielectric(ThinDielectricBxDF::new(sampled_eta));
|
||||
|
|
|
|||
|
|
@ -7,14 +7,17 @@ use crate::spectra::{SampledSpectrum, SampledWavelengths};
|
|||
use crate::utils::{Ptr, math::square};
|
||||
use num_traits::Float as NumFloat;
|
||||
|
||||
fn checkerboard(
|
||||
ctx: &TextureEvalContext,
|
||||
map2d: Ptr<TextureMapping2D>,
|
||||
map3d: Ptr<TextureMapping3D>,
|
||||
) -> Float {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum CheckerMap {
|
||||
D2(TextureMapping2D),
|
||||
D3(TextureMapping3D),
|
||||
}
|
||||
|
||||
fn checkerboard(ctx: &TextureEvalContext, checker_map: CheckerMap) -> Float {
|
||||
let d = |x: Float| -> Float {
|
||||
let y = x / 2. - (x / 2.).floor() - 0.5;
|
||||
return x / 2. + y * (1. - 2. * y.abs());
|
||||
x / 2. + y * (1. - 2. * y.abs())
|
||||
};
|
||||
|
||||
let bf = |x: Float, r: Float| -> Float {
|
||||
|
|
@ -24,48 +27,52 @@ fn checkerboard(
|
|||
(d(x + r) - 2. * d(x) + d(x - r)) / square(r)
|
||||
};
|
||||
|
||||
if !map2d.is_null() {
|
||||
assert!(map3d.is_null());
|
||||
let c = map2d.map(&ctx);
|
||||
let ds = 1.5 * c.dsdx.abs().max(c.dsdy.abs());
|
||||
let dt = 1.5 * c.dtdx.abs().max(c.dtdy.abs());
|
||||
// Integrate product of 2D checkerboard function and triangle filter
|
||||
0.5 - bf(c.st[0], ds) * bf(c.st[1], dt) / 2.
|
||||
} else {
|
||||
assert!(!map3d.is_null());
|
||||
let c = map3d.map(&ctx);
|
||||
let dx = 1.5 * c.dpdx.x().abs().max(c.dpdy.x().abs());
|
||||
let dy = 1.5 * c.dpdx.y().abs().max(c.dpdy.y().abs());
|
||||
let dz = 1.5 * c.dpdx.z().abs().max(c.dpdy.z().abs());
|
||||
0.5 - bf(c.p.x(), dx) * bf(c.p.y(), dy) * bf(c.p.z(), dz)
|
||||
match checker_map {
|
||||
CheckerMap::D2(map) => {
|
||||
let c = map.map(ctx);
|
||||
let ds = 1.5 * c.dsdx.abs().max(c.dsdy.abs());
|
||||
let dt = 1.5 * c.dtdx.abs().max(c.dtdy.abs());
|
||||
// Integrate product of 2D checkerboard function and triangle filter
|
||||
0.5 - bf(c.st[0], ds) * bf(c.st[1], dt) / 2.
|
||||
}
|
||||
CheckerMap::D3(map) => {
|
||||
let c = map.map(ctx);
|
||||
let dx = 1.5 * c.dpdx.x().abs().max(c.dpdy.x().abs());
|
||||
let dy = 1.5 * c.dpdx.y().abs().max(c.dpdy.y().abs());
|
||||
let dz = 1.5 * c.dpdx.z().abs().max(c.dpdy.z().abs());
|
||||
0.5 - bf(c.p.x(), dx) * bf(c.p.y(), dy) * bf(c.p.z(), dz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct FloatCheckerboardTexture {
|
||||
pub map2d: Ptr<TextureMapping2D>,
|
||||
pub map3d: Ptr<TextureMapping3D>,
|
||||
pub map: CheckerMap,
|
||||
pub tex: [Ptr<FloatTexture>; 2],
|
||||
}
|
||||
|
||||
impl FloatCheckerboardTexture {
|
||||
pub fn new(map: CheckerMap, tex: [Ptr<FloatTexture>; 2]) -> Self {
|
||||
Self { map, tex }
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let w = checkerboard(&ctx, self.map2d, self.map3d);
|
||||
let w = checkerboard(ctx, self.map);
|
||||
|
||||
let mut t0 = 0.0;
|
||||
let mut t1 = 0.0;
|
||||
|
||||
if w != 1.0 {
|
||||
if let Some(tex) = self.tex[0].get() {
|
||||
t0 = tex.evaluate(ctx);
|
||||
}
|
||||
if w != 1.0
|
||||
&& let Some(tex) = self.tex[0].get()
|
||||
{
|
||||
t0 = tex.evaluate(ctx);
|
||||
}
|
||||
|
||||
if w != 0.0 {
|
||||
if let Some(tex) = self.tex[1].get() {
|
||||
t1 = tex.evaluate(ctx);
|
||||
}
|
||||
if w != 0.0
|
||||
&& let Some(tex) = self.tex[1].get()
|
||||
{
|
||||
t1 = tex.evaluate(ctx);
|
||||
}
|
||||
|
||||
(1.0 - w) * t0 + w * t1
|
||||
|
|
@ -75,30 +82,33 @@ impl FloatCheckerboardTexture {
|
|||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct SpectrumCheckerboardTexture {
|
||||
pub map2d: Ptr<TextureMapping2D>,
|
||||
pub map3d: Ptr<TextureMapping3D>,
|
||||
pub map: CheckerMap,
|
||||
pub tex: [Ptr<SpectrumTexture>; 2],
|
||||
}
|
||||
|
||||
impl SpectrumCheckerboardTexture {
|
||||
pub fn new(map: CheckerMap, tex: [Ptr<SpectrumTexture>; 2]) -> Self {
|
||||
Self { map, tex }
|
||||
}
|
||||
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
ctx: &TextureEvalContext,
|
||||
lambda: &SampledWavelengths,
|
||||
) -> SampledSpectrum {
|
||||
let w = checkerboard(ctx, self.map2d, self.map3d);
|
||||
let w = checkerboard(ctx, self.map);
|
||||
let mut t0 = SampledSpectrum::new(0.);
|
||||
let mut t1 = SampledSpectrum::new(0.);
|
||||
if w != 1.0 {
|
||||
if let Some(tex) = self.tex[0].get() {
|
||||
t0 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
if w != 1.0
|
||||
&& let Some(tex) = self.tex[0].get()
|
||||
{
|
||||
t0 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
|
||||
if w != 0.0 {
|
||||
if let Some(tex) = self.tex[1].get() {
|
||||
t1 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
if w != 0.0
|
||||
&& let Some(tex) = self.tex[1].get()
|
||||
{
|
||||
t1 = tex.evaluate(ctx, lambda);
|
||||
}
|
||||
|
||||
t0 * (1.0 - w) + t1 * w
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use crate::Float;
|
||||
use crate::core::geometry::{Point2f, VectorLike};
|
||||
use crate::core::texture::{
|
||||
FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D,
|
||||
};
|
||||
use crate::core::texture::{FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D};
|
||||
use crate::spectra::sampled::{SampledSpectrum, SampledWavelengths};
|
||||
use crate::utils::Ptr;
|
||||
use crate::utils::math::square;
|
||||
|
|
@ -22,18 +20,30 @@ fn inside_polka_dot(st: Point2f) -> bool {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
false
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FloatDotsTexture {
|
||||
pub mapping: TextureMapping2D,
|
||||
pub outside_dot: Ptr<FloatTexture>,
|
||||
pub inside_dot: Ptr<FloatTexture>,
|
||||
pub outside_dot: Ptr<FloatTexture>,
|
||||
}
|
||||
|
||||
impl FloatDotsTexture {
|
||||
pub fn new(
|
||||
mapping: TextureMapping2D,
|
||||
inside_dot: Ptr<FloatTexture>,
|
||||
outside_dot: Ptr<FloatTexture>,
|
||||
) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
inside_dot,
|
||||
outside_dot,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let c = self.mapping.map(ctx);
|
||||
let target_texture = if inside_polka_dot(c.st) {
|
||||
|
|
@ -54,11 +64,22 @@ impl FloatDotsTexture {
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct SpectrumDotsTexture {
|
||||
pub mapping: TextureMapping2D,
|
||||
pub outside_dot: Ptr<SpectrumTexture>,
|
||||
pub inside_dot: Ptr<SpectrumTexture>,
|
||||
pub outside_dot: Ptr<SpectrumTexture>,
|
||||
}
|
||||
|
||||
impl SpectrumDotsTexture {
|
||||
pub fn new(
|
||||
mapping: TextureMapping2D,
|
||||
inside_dot: Ptr<SpectrumTexture>,
|
||||
outside_dot: Ptr<SpectrumTexture>,
|
||||
) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
inside_dot,
|
||||
outside_dot,
|
||||
}
|
||||
}
|
||||
pub fn evaluate(
|
||||
&self,
|
||||
ctx: &TextureEvalContext,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,18 @@ use crate::utils::noise::fbm;
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FBmTexture {
|
||||
pub mapping: TextureMapping3D,
|
||||
pub omega: Float,
|
||||
pub octaves: u32,
|
||||
pub omega: Float,
|
||||
}
|
||||
|
||||
impl FBmTexture {
|
||||
pub fn new(mapping: TextureMapping3D, octaves: u32, omega: Float) -> Self {
|
||||
Self {
|
||||
mapping,
|
||||
omega,
|
||||
octaves,
|
||||
}
|
||||
}
|
||||
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
|
||||
let c = self.mapping.map(ctx);
|
||||
fbm(c.p, c.dpdx, c.dpdy, self.omega, self.octaves)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ impl CreateFloatTexture for FloatBilerpTexture {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumBilerpTexture {
|
||||
fn create(
|
||||
render_from_texture: Transform,
|
||||
|
|
@ -43,9 +42,7 @@ impl CreateSpectrumTexture for SpectrumBilerpTexture {
|
|||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
|
||||
// `Spectrum` is already a device type, so it is allocated into the arena
|
||||
// rather than uploaded -- upload is for host trees (Arc) -> device (Ptr).
|
||||
let mut get = |name: &str, def: Spectrum| {
|
||||
let get = |name: &str, def: Spectrum| {
|
||||
let s = parameters
|
||||
.get_one_spectrum(name, Some(def), spectrum_type)
|
||||
.unwrap_or(def);
|
||||
|
|
|
|||
|
|
@ -1,37 +1,79 @@
|
|||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, bail};
|
||||
use shared::{
|
||||
core::texture::SpectrumType,
|
||||
textures::{FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
||||
utils::Transform
|
||||
core::spectrum::Spectrum,
|
||||
core::texture::{SpectrumType, TextureMapping2D, TextureMapping3D},
|
||||
spectra::ConstantSpectrum,
|
||||
textures::{CheckerMap, FloatCheckerboardTexture, SpectrumCheckerboardTexture},
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
||||
SpectrumTexture,
|
||||
},
|
||||
utils::{ArenaUpload, FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
fn checker_map(
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
) -> Result<CheckerMap> {
|
||||
match parameters.get_one_int("dimension", 2)? {
|
||||
2 => Ok(CheckerMap::D2(TextureMapping2D::create(
|
||||
¶meters,
|
||||
&render_from_texture,
|
||||
&loc,
|
||||
)?)),
|
||||
3 => Ok(CheckerMap::D3(TextureMapping3D::create(
|
||||
¶meters,
|
||||
&render_from_texture,
|
||||
&loc,
|
||||
)?)),
|
||||
dim => bail!("{loc}: {dim} dimensional checkerboard texture not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateFloatTexture for FloatCheckerboardTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
let tex1 = arena.upload(parameters.get_float_texture("tex1", 1.)?);
|
||||
let tex2 = arena.upload(parameters.get_float_texture("tex2", 0.)?);
|
||||
let map = checker_map(render_from_texture, parameters, loc)?;
|
||||
let tex = FloatCheckerboardTexture::new(map, [tex1, tex2]);
|
||||
Ok(FloatTexture::Checkerboard(tex))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumCheckerboardTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
let tex = |name: &str, def: Spectrum| {
|
||||
arena.upload(
|
||||
parameters
|
||||
.get_spectrum_texture(name, Some(def), spectrum_type)
|
||||
.expect("default supplied"),
|
||||
)
|
||||
};
|
||||
|
||||
let tex1 = tex("tex1", one);
|
||||
let tex2 = tex("tex2", zero);
|
||||
|
||||
let map = checker_map(render_from_texture, parameters, loc)?;
|
||||
let tex = SpectrumCheckerboardTexture::new(map, [tex1, tex2]);
|
||||
Ok(SpectrumTexture::Checkerboard(tex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,57 @@
|
|||
use crate::Arena;
|
||||
use crate::{Arena, ArenaUpload};
|
||||
use anyhow::Result;
|
||||
use shared::{
|
||||
core::texture::SpectrumType,
|
||||
core::spectrum::Spectrum,
|
||||
core::texture::{SpectrumType, TextureMapping2D},
|
||||
spectra::ConstantSpectrum,
|
||||
textures::{FloatDotsTexture, SpectrumDotsTexture},
|
||||
utils::Transform
|
||||
utils::Transform,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
core::texture::{
|
||||
CreateFloatTexture, CreateSpectrumTexture, FloatTexture, SpectrumTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
CreateFloatTexture, CreateSpectrumTexture, CreateTextureMapping, FloatTexture,
|
||||
SpectrumTexture,
|
||||
},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for FloatDotsTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let inside = parameters.get_float_texture("inside", 1.)?;
|
||||
let outside = parameters.get_float_texture("outside", 1.)?;
|
||||
|
||||
let tex = FloatDotsTexture::new(map, arena.upload(inside), arena.upload(outside));
|
||||
|
||||
Ok(FloatTexture::Dots(tex))
|
||||
}
|
||||
}
|
||||
|
||||
impl CreateSpectrumTexture for SpectrumDotsTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_spectrum_type: SpectrumType,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
spectrum_type: SpectrumType,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<SpectrumTexture> {
|
||||
todo!()
|
||||
let map = TextureMapping2D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let zero = Spectrum::Constant(ConstantSpectrum::new(0.));
|
||||
let one = Spectrum::Constant(ConstantSpectrum::new(1.));
|
||||
|
||||
let get = |name: &str, def: Spectrum| {
|
||||
let t = parameters
|
||||
.get_spectrum_texture(name, Some(def), spectrum_type)
|
||||
.expect("default supplied");
|
||||
arena.upload(t)
|
||||
};
|
||||
let tex = SpectrumDotsTexture::new(map, get("inside", one), get("outside", zero));
|
||||
Ok(SpectrumTexture::Dots(tex))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,26 @@
|
|||
use crate::Arena;
|
||||
use anyhow::Result;
|
||||
use shared::core::texture::TextureEvalContext;
|
||||
use shared::core::texture::{TextureEvalContext, TextureMapping3D};
|
||||
use shared::{textures::FBmTexture, utils::Transform};
|
||||
|
||||
use crate::{
|
||||
core::texture::{CreateFloatTexture, FloatTexture },
|
||||
utils::{FileLoc, TextureParameterDictionary}
|
||||
core::texture::{CreateFloatTexture, CreateTextureMapping, FloatTexture},
|
||||
utils::{FileLoc, TextureParameterDictionary},
|
||||
};
|
||||
|
||||
impl CreateFloatTexture for FBmTexture {
|
||||
fn create(
|
||||
_render_from_texture: Transform,
|
||||
_parameters: TextureParameterDictionary,
|
||||
_loc: FileLoc,
|
||||
_arena: &Arena,
|
||||
render_from_texture: Transform,
|
||||
parameters: TextureParameterDictionary,
|
||||
loc: FileLoc,
|
||||
arena: &Arena,
|
||||
) -> Result<FloatTexture> {
|
||||
todo!()
|
||||
let map = TextureMapping3D::create(¶meters, &render_from_texture, &loc)?;
|
||||
let tex = FBmTexture::new(
|
||||
map,
|
||||
parameters.get_one_int("octaves", 5)?.try_into().unwrap(),
|
||||
parameters.get_one_float("roughness", 0.5)?,
|
||||
);
|
||||
Ok(FloatTexture::FBm(tex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue