Skip to content

Release Notes

Jan Walter edited this page Oct 12, 2020 · 109 revisions

Release Notes

v0.8.3.

Release Notes for v0.8.3

v0.8.2.

Release Notes for v0.8.2

v0.8.1.

Release Notes for v0.8.1

v0.8.0.

Release Notes for v0.8.0

v0.7.3.

Release Notes for v0.7.3

v0.7.2.

Release Notes for v0.7.2

v0.7.1.

Release Notes for v0.7.1

v0.7.0.

Release Notes for v0.7.0

v0.6.2.

Release Notes for v0.6.2

v0.6.1.

Release Notes for v0.6.1

v0.6.0.

Release Notes for v0.6.0

v0.5.3.

Release Notes for v0.5.3

v0.5.2.

Release Notes for v0.5.2

v0.5.1.

Release Notes for v0.5.1

v0.5.0.

Release Notes for v0.5.0

v0.4.5.

The release notes are published here from now on.

v0.4.4.

There are mainly two new shapes being supported to be read from .pbrt files:

  1. NURBS (Non-Uniform Rational B-Splines) - see shapes/nurbs
  2. Subdivision Surfaces - see shapes/loopsubdiv

The related issues are:

  1. CreateNURBS (see issue #65)
  2. Implement 'Shape "loopsubdiv"' (see issue #67)
  3. Fix motion blur (see issue #66)

I started to implement some Python scripts for Blender to export to rs_pbrt. This is basically a simple way to create basic scene files for certain features of the renderer I'm working on. The repository also contains 4 new test scenes related to those topics.

v0.4.3.

I added a new test scene to the GitLab repository, which caused a lot of issues and TODOs:

  1. The first task (see issue #56) I opened, was about rendering the (new) VW scene. Which surely would create new issues.
  2. The parser had to be changed to allow spaces in identifiers (e.g. for materials). The related issue #57 can be re-opened in the future for any parser related problems for reading/parsing .pbrt scene files.
  3. While working on the parser I saw that the test scene contains ObjectBegin, ObjectEnd, and ObjectInstance keywords and I opened a separate enhancement issue (see issue #58) for that.
  4. There was one material in particular which specified two filenames for Spectrum parameters. We had to deal with those filenames via ParamSet::add_sampled_spectrum_files(). See issue #59 but also read the content of those files via read_float_file() (see issue #60).
  5. The test scene contained a new FourierMaterial, which also had a parameter which reads BSDF information from a file. So we needed two more structs: FourierBSDFTable and FourierBSDF. See issue #61.
  6. After implementing all the Bxdf trait methods for FourierBSDF I triggered a panic during rendering of the test scene. While debugging the problem I figured out that I had to go back to the ObjectInstance lines, which do influence the scene bound, which is used e.g. by InfiniteAreaLight. Issue #63 deals with that aspect, but it didn't fix the panic.
  7. I created issue #64 in the hope that I had identified the cause, but in the end I had to fix a couple of things which I identified during debugging and comparing the original C++ version with the current Rust code.

The two sampled spectrum files are now part of this repository and there is a new executable to test the function to read those kind of files (see floatfile documentation):

$ ./target/release/examples/core_read_float_file
read_float_file("/home/jan/git/self_hosted/Rust/pbrt/assets/spds/Al.k.spd", ...) returns true.
[298.75705, 3.59375, 302.40042, 3.64, 306.13376, 3.689375, 309.96045, 3.74, 313.884, 3.789375, 317.90814, 3.84, 322.03683, 3.894375, 326.27414, 3.95, 330.62448, 4.005, 335.09238, 4.06, 339.68268, 4.11375, 344.40048, 4.17, 349.25122, 4.23375, 354.2405, 4.3, 359.37442, 4.365, 364.65933, 4.43, 370.10202, 4.49375, 375.70963, 4.56, 381.48978, 4.63375, 387.45056, 4.71, 393.60056, 4.784375, 399.94897, 4.86, 406.5055, 4.938125, 413.28058, 5.02, 420.28534, 5.10875, 427.53165, 5.2, 435.0322, 5.29, 442.80063, 5.38, 450.85156, 5.48, 459.20065, 5.58, 467.86484, 5.69, 476.8622, 5.8, 486.21246, 5.915, 495.9367, 6.03, 506.05786, 6.15, 516.60077, 6.28, 527.5922, 6.42, 539.06165, 6.55, 551.0408, 6.7, 563.56445, 6.85, 576.6706, 7.0, 590.4008, 7.15, 604.80084, 7.31, 619.9209, 7.48, 635.8163, 7.65, 652.5483, 7.82, 670.18475, 8.01, 688.80096, 8.21, 708.481, 8.39, 729.31866, 8.57, 751.41925, 8.62, 774.9011, 8.6, 799.89795, 8.45, 826.56116, 8.31, 855.0633, 8.21, 885.60126, 8.21]
read_float_file("/home/jan/git/self_hosted/Rust/pbrt/assets/spds/Al.eta.spd", ...) returns true.
[298.75705, 0.273375, 302.40042, 0.28, 306.13376, 0.286813, 309.96045, 0.294, 313.884, 0.301875, 317.90814, 0.31, 322.03683, 0.317875, 326.27414, 0.326, 330.62448, 0.33475, 335.09238, 0.344, 339.68268, 0.353813, 344.40048, 0.364, 349.25122, 0.374375, 354.2405, 0.385, 359.37442, 0.39575, 364.65933, 0.407, 370.10202, 0.419125, 375.70963, 0.432, 381.48978, 0.445688, 387.45056, 0.46, 393.60056, 0.474688, 399.94897, 0.49, 406.5055, 0.506188, 413.28058, 0.523, 420.28534, 0.540063, 427.53165, 0.558, 435.0322, 0.577313, 442.80063, 0.598, 450.85156, 0.620313, 459.20065, 0.644, 467.86484, 0.668625, 476.8622, 0.695, 486.21246, 0.72375, 495.9367, 0.755, 506.05786, 0.789, 516.60077, 0.826, 527.5922, 0.867, 539.06165, 0.912, 551.0408, 0.963, 563.56445, 1.02, 576.6706, 1.08, 590.4008, 1.15, 604.80084, 1.22, 619.9209, 1.3, 635.8163, 1.39, 652.5483, 1.49, 670.18475, 1.6, 688.80096, 1.74, 708.481, 1.91, 729.31866, 2.14, 751.41925, 2.41, 774.9011, 2.63, 799.89795, 2.8, 826.56116, 2.74, 855.0633, 2.58, 885.60126, 2.24]

I also had to implement several spline-based interpolation functions (see interpolation for documentation). The biggest changes were made in fourier (FourierMaterial) and reflection (FourierBSDF, FourierBSDFTable).

Version 0.4.3 consists of 120 public structs, 9 enums, 23 traits, and 188 public functions:

> pwd
/home/jan/git/github/rs_pbrt/src
> rg -trust "^pub struct" | wc
    120     483    5430
> rg -trust "^pub enum" | wc
      9      36     371
> rg -trust "^pub trait" | wc
     23      96     972
> rg -trust "^pub fn" | wc
    188    1428   13712

v0.4.2.

I started working on a parser, which can use another renderers scene description (in this case Arnold’s .ass files). It's in a very early stage of implementation but it can be used on a couple of test scenes already:

> ./target/release/examples/parse_ass_file -h
Usage: ./target/release/examples/parse_ass_file [options]

Options:
    -h, --help          print this help menu
    -i FILE             parse an input file
    -s, --samples NUM   samples per pixel
    -v, --version       print version number

Currently we allow to specify the number of samples per pixel on the command line, but limit the numbers to 8 bit (u8). In the future it will likely be raised to 16 bit unsigned integer numbers:

> ./target/release/examples/parse_ass_file -i assets/ass/cornell_box.ass -s 128

The three test scenes provided are:

> ls -1 assets/ass/c*.ass
assets/ass/cafe_scene1.ass
assets/ass/cafe_scene2.ass
assets/ass/cornell_box.ass

I also worked on the parser a bit to be able to render a test scene from the Blender to PBRTv3 exporter. Look at the resulting image at the GitLab repository gathering test scenes for this Rust based implementation of PBRT. The .ass files for Arnold (mentioned above) can be found there as well.

v0.4.1.

Since the last release where the main executable (rs_pbrt) was ported to the latest pest crate version, a couple of problems were introduced and were unnoticed until you try to render some test scenes.

Otherwise I worked mainly on three issues:

  1. Basically I wanted to be able to use Float image textures (see issue #52), as well as Spectrum textures (which I had implemented already).
  2. While working on that I found a bug (see issue #53), in case the scene description was missing the Integrator line (which was really easy to fix - the default string was wrong).
  3. I also needed a better test scene to see that those Float textures are read and handled correctly. Therefore I added a scene for bump mapping which had one imagemap texture to control where the bump mapping is supposed to happen, and one ScaleTexture to scale the effect (by a constant value). See issue #54

Version 0.4.1 consists of 116 public structs, 9 enums, 23 traits, and 179 public functions:

> pwd
/home/jan/git/github/rs_pbrt/src
> rg -trust "^pub struct" | wc
    116     467    5252
> rg -trust "^pub enum" | wc
      9      36     371
> rg -trust "^pub trait" | wc
     23      96     972
> rg -trust "^pub fn" | wc
    179    1366   13070

Here are the traits:

> rg -trust "^pub trait" 
core/reflection.rs
253:pub trait Bxdf {
307:pub trait Fresnel {

core/mipmap.rs
392:pub trait Clampable {

core/primitive.rs
16:pub trait Primitive {

core/filter.rs
11:pub trait Filter {

core/camera.rs
16:pub trait Camera {

core/microfacet.rs
12:pub trait MicrofacetDistribution {

core/medium.rs
266:pub trait PhaseFunction {
271:pub trait Medium {

core/light.rs
26:pub trait Light {
126:pub trait AreaLight: Light {

textures/imagemap.rs
103:pub trait ImageTextureConvert<T> {

core/interaction.rs
28:pub trait Interaction {

core/texture.rs
17:pub trait TextureMapping2D {
77:pub trait Texture<T> {

core/shape.rs
16:pub trait Shape {

core/integrator.rs
23:pub trait SamplerIntegrator {

core/lightdistrib.rs
22:pub trait LightDistribution {

core/material.rs
26:pub trait Material {

core/sampler.rs
12:pub trait Sampler: SamplerClone {
36:pub trait PixelSampler: Sampler {}
38:pub trait GlobalSampler: Sampler {}
40:pub trait SamplerClone {

v0.4.0.

The current version should compile with all three Rust versions (stable, beta, nightly).

The main executable to render test scenes is called rs_pbrt:

> ./target/release/examples/rs_pbrt -v
./target/release/examples/rs_pbrt 0.4.0

Issue #39 was resolved and the latest version of the pest crate is being used.

The atomic crate was upgraded to version 0.4.

Most of the functionality which is independent of the parser, moved into the API.

All global variables within the parser are gone. They are all collected within ApiState (see link) and there is no need for unsafe code blocks to deal with them.

All test scenes are collected on GitLab.

Version 0.4.0 consists of 115 public structs, 9 enums, 21 traits, and 176 public functions:

> pwd
/home/jan/git/github/rs_pbrt/src
> rg -trust "^pub struct" | wc
    115     463    5659
> rg -trust "^pub enum" | wc
      9      36     407
> rg -trust "^pub trait" | wc
     21      88     963
> rg -trust "^pub fn" | wc
    176    1349   13591

Here are the traits:

> rg -trust "^pub trait" 
src/core/microfacet.rs
12:pub trait MicrofacetDistribution {

src/core/texture.rs
17:pub trait TextureMapping2D {
77:pub trait Texture<T> {

src/core/lightdistrib.rs
22:pub trait LightDistribution {

src/core/interaction.rs
28:pub trait Interaction {

src/core/shape.rs
16:pub trait Shape {

src/core/integrator.rs
23:pub trait SamplerIntegrator {

src/core/primitive.rs
16:pub trait Primitive {

src/core/light.rs
26:pub trait Light {
126:pub trait AreaLight: Light {

src/core/camera.rs
16:pub trait Camera {

src/core/material.rs
20:pub trait Material {

src/core/sampler.rs
12:pub trait Sampler: SamplerClone {
36:pub trait PixelSampler: Sampler {}
38:pub trait GlobalSampler: Sampler {}
40:pub trait SamplerClone {

src/core/medium.rs
266:pub trait PhaseFunction {
271:pub trait Medium {

src/core/reflection.rs
253:pub trait Bxdf {
307:pub trait Fresnel {

src/core/filter.rs
11:pub trait Filter {

v0.3.2

Version 0.3.2 can render with Metropolis Light Transport now. See blog post to see some images.

The openexr crate got upgraded to version 0.6. The MLT main render loop does use the rayon crate (a data-parallelism library) to run several Markov chains in parallel (using par_iter()).

There are two progress bars for the two stages of rendering. The first one isn't very clever and should probably be changed in the future. Basically a large vector of float values (bootstrap samples) is split into num_cores chunks and each processor is dealing with one chunk. After that the main render loop indicates with a progress bar the number of Markov chains which were already dealt with, and an estimate about the remaining render time.

All three render functions use Arc now for the camera pointer (instead of a Box).

There is a new linear interpolation function (lerp) for Bounds2.

The signatures of VisibilityTester::tr(...) and Medium::tr(...) changed.

New constant SQRT_2 in core/pbrt.rs and new function erf_inv(...).

Four issues were closed:

  1. bootstrap samples differ (see issue #48)
  2. Implement MLTIntegrator (see issue #43)
  3. Show status of MLT render loop via progress bars (see issue #49)
  4. Fix "black windows" for bi-directional path tracing (see issue #50)

v0.3.1

Version 0.3.1 can render volumetric caustics now:

A glass sphere in participating media, showing off a volumetric caustic.

new file assets/scenes/caustic.pbrt

Test scene for image above (see also issue #46).

new file examples/geometry_spherical_direction_vec3.rs

During debugging I figured out that I got slightly different values between the C++ version and Rust. This file is a reminder and multiplying the two Float values first, before multiplying the result with a Vector3f, makes a difference:

-    *x * sin_theta * phi.cos() + *y * sin_theta * phi.sin() + *z * cos_theta
+    *x * (sin_theta * phi.cos()) + *y * (sin_theta * phi.sin()) + *z * cos_theta

new file src/core/medium.rs

Contains three new structs:

$ grep "^pub struct" src/core/medium.rs 
pub struct MeasuredSS {
pub struct HenyeyGreenstein {
pub struct MediumInterface {

One new constant:

$ grep "^pub const" src/core/medium.rs 
pub const SUBSURFACE_PARAMETER_TABLE: [MeasuredSS; 47] = [

Two new traits:

$ grep "^pub trait" src/core/medium.rs 
pub trait PhaseFunction {
pub trait Medium {

And two new functions:

$ grep "^pub fn" src/core/medium.rs 
pub fn get_medium_scattering_properties(
pub fn phase_hg(cos_theta: Float, g: Float) -> Float {

new file src/integrators/mlt.rs

I started to implement the MLTIntegrator (see issue #43), but for now we only got some skeleton code:

Contains two new structs:

jan@purism:~/git/self_hosted/Rust/pbrt$ grep "^pub struct" src/integrators/mlt.rs 
pub struct MLTSampler {
pub struct MLTIntegrator {

Two new constants:

jan@purism:~/git/self_hosted/Rust/pbrt$ grep "^pub const" src/integrators/mlt.rs 
pub const CAMERA_STREAM_INDEX: u8 = 0;
pub const N_SAMPLE_STREAMS: u8 = 3;

new file src/lights/spot.rs

For the test scene with volumetric caustics we needed a SpotLight (see issue #21).

new file src/media/homogeneous.rs

Contains:

pub struct HomogeneousMedium {
    pub sigma_a: Spectrum,
    pub sigma_s: Spectrum,
    pub sigma_t: Spectrum,
    pub g: Float,
}

Which implements the Medium trait.

new file src/media/mod.rs

See media in the documentation.

v0.3.0

Version 0.3.0 can render with bi-directional path tracing (BDPT) now:

Comparison between uni- and bi-directional path tracing

On the left the same scene was rendered with uni-directional path tracing and the resulting image contains much more noise, on the right bi-directional path tracing was used (with otherwise identical settings). Rays leaving the scene without hitting geometry render black right now (see windows). This should be fixed for future releases.

Here is another scene which profits from using BDPT:

Art gallery rendered with bi-directional path tracing

Version 0.3.0 consists of 105 public structs, 9 enums, 19 traits, and 138 public functions:

> pwd
/home/jan/git/github/rs_pbrt/src
> rg -trust "^pub struct" | wc
    105     423    4739
> rg -trust "^pub enum" | wc
      9      36     371
> rg -trust "^pub trait" | wc
     19      80     802
> rg -trust "^pub fn" | wc
    138    1061   10024

Here are the traits:

> rg -trust "^pub trait" 
core/microfacet.rs
12:pub trait MicrofacetDistribution {

core/texture.rs
17:pub trait TextureMapping2D {
77:pub trait Texture<T> {

core/lightdistrib.rs
21:pub trait LightDistribution {

core/interaction.rs
27:pub trait Interaction {

core/shape.rs
16:pub trait Shape {

core/integrator.rs
20:pub trait SamplerIntegrator {

core/primitive.rs
15:pub trait Primitive {

core/light.rs
23:pub trait Light {
113:pub trait AreaLight: Light {

core/sampler.rs
12:pub trait Sampler: SamplerClone {
36:pub trait PixelSampler: Sampler {
39:pub trait GlobalSampler: Sampler {
42:pub trait SamplerClone {

core/material.rs
20:pub trait Material {

core/reflection.rs
253:pub trait Bxdf {
307:pub trait Fresnel {

core/filter.rs
11:pub trait Filter {

core/camera.rs
16:pub trait Camera {

v0.2.7

  1. Implemented SubstrateMaterial issue #34.
  2. Taking ReverseOrientation in a .pbrt scene into account.
  3. Fix a problem for InfiniteAreaLight and HDR images.
  4. Fix a problem with world-space normals and uv-coords.
  5. Implemented TriangleFilter (this resolves issue #18).
  6. Implemented UberMaterial issue #35.
  7. Deal with TransformBegin and TransformEnd (see issue #36).
  8. Fixed two bugs, one for mipmaps, the other for Bsdfs.
  9. Implemented the curve shape (see issue #37).
  10. Implemented HairMaterial issue #38.
  11. Have a default matte material for the GraphicsState.

Ganesha Statue

Very detailed scan of a small statue with over 4.3 million triangles, illuminated by a few area light sources.

Ganesha Statue

The ground object consists of two triangles using the default matte material, the ganesha statue is using a substrate material with a texture.

Classroom

The Japanese Classroom scene comes from Benedikt Bitterli’s Rendering Resources.

Classroom room rendered by rs_pbrt

While debugging this scene (see issue #36) I noticed that the parser didn't deal with TransformBegin and TransformEnd (yet) and fixed that.

There are other scenes which I was able to render with the Rust version of PBRT and the resulting images can be seen here. The PBRT scene files were slightly modified and can be downloaded from my web site (at the bottom of the download page).

Hair

The hair scattering model in action:

Curly and straight hair rendered by Rust version of PBRT

v0.2.6

  1. Created and solved issue #27 for using PLY files.
  2. Fix a bug in ParamSet::copy_from(...) to deal with boolean parameters (see issue #28).
  3. New test scene for bi-directional path-tracing (see issue #29).
  4. Implemented and tested the RandomSampler (see issue #26).
  5. New test scene for depth of field.
  6. New material MetalMaterial (see issue #30).
  7. Implemented depth of field (see issue #31).
  8. Building without OpenEXR on Travis CI.
  9. Add images and more text to the documentation.
  10. Allow blackbody param type (see issue #32).
  11. Implement MixMaterial with the help of ScaledBxDF (see issue #33).

Depth of Field

Test scene for depth of field

Multiple Importance Sampling

Test scene for multiple importance sampling

Updated/New Scene from the PBRT Input File Documentation

Updated/new scene from the PBRT input file documentation

Breakfast Test Scene

New Breakfast Test Scene

v0.2.5

  1. We can build with or without OpenEXR now.
  2. Via the image::hdr crate/module we can use HDR images.
  3. The single lib.rs file was split into many files and folders.
  4. Implemented two new samplers: HaltonSampler and SobolSampler.

To compile without OpenEXR you can use this command line:

cargo test --release --no-default-features

The test scene for motion blur uses a Radiance HDR file now:

-LightSource "infinite" "string mapname" ["textures/skylight-day.exr"]
+LightSource "infinite" "string mapname" ["textures/skylight-day.hdr"]

The conversion from OpenEXR to HDR can be done within Blender.

The documentation is now more structured (using modules, and splitting the core into sub-modules).

ZeroTwoSequenceSampler

+Sampler "lowdiscrepancy" "integer pixelsamples" [8]

Using the "lowdiscrepancy" or "02sequence" sampler.

HaltonSampler

+Sampler "halton" "integer pixelsamples" [8]

Using the "halton" sampler.

SobolSampler

+Sampler "sobol" "integer pixelsamples" [8]

Using the "sobol" sampler.

Version 0.2.5 consists of 88 public structs, 6 enums, 17 traits, and 117 public functions:

> pwd
/home/jan/git/github/rs_pbrt/src
> rg -trust "^pub struct" | wc
     88     353    3927
> rg -trust "^pub enum" | wc
      6      24     251
> rg -trust "^pub trait" | wc
     17      70     701
> rg -trust "^pub fn" | wc
    117     955    8752

Here are the traits:

> rg -trust "^pub trait" 
textures/mod.rs
15:pub trait TextureMapping2D {
75:pub trait Texture<T> {

materials/mod.rs
14:pub trait Material {

shapes/mod.rs
241:pub trait Shape {

filters/mod.rs
90:pub trait Filter {

core/microfacet.rs
12:pub trait MicrofacetDistribution {

core/interaction.rs
29:pub trait Interaction {

core/lightdistrib.rs
17:pub trait LightDistribution {

core/primitive.rs
16:pub trait Primitive {

core/light.rs
17:pub trait Light {
67:pub trait AreaLight: Light {

core/camera.rs
10:pub trait Camera {

core/sampler.rs
8:pub trait Sampler: SamplerClone {
22:pub trait SamplerClone {

core/reflection.rs
240:pub trait Bxdf {
262:pub trait Fresnel {

core/integrator.rs
20:pub trait SamplerIntegrator {

The rg (or ripgrep executable) comes from the ripgrep GitHub repository, but can be installed via cargo:

> cargo install ripgrep

v0.2.4

The main features are:

  1. We have an InfiniteAreaLight now. See issue #20.
  2. We had to be able to read a HDR image for image based lighting.
  3. We do support basic motion blur. See issue #24.
  4. We allow to specify the number of threads on the command line.

Three textured spheres and motion blur.

> ./target/release/examples/pest_test -h
Usage: ./target/release/examples/pest_test [options]

Options:
    -h, --help          print this help menu
    -i FILE             parse an input file
    -t, --nthreads NUM  use specified number of threads for rendering
    -v, --version       print version number

As a consequence we rely on the openexr crate now. This complicates cross platform development and continuous integration via Travis CI. Therefore I would like to replace it by using Radiance HDR image supported by the image crate.

Added new structs:

pub struct Interval
pub struct TransformedPrimitive
pub struct ResampleWeight
pub struct InfiniteAreaLight
pub struct Distribution2D

New functions:

pub fn spherical_theta(v: &Vector3f) -> Float
pub fn spherical_phi(v: &Vector3f) -> Float
pub fn interval_sin(i: Interval) -> Interval
pub fn interval_cos(i: Interval) -> Interval
pub fn interval_find_zeros(c1: Float, ... , depth: usize)
pub fn quat_slerp(t: Float, q1: Quaternion, q2: Quaternion) -> Quaternion
pub fn lanczos(x: Float, tau: Float) -> Float

Renamed functions or changed signatures:

pub fn clamp_t<T>(val: T, low: T, high: T) -> T
pub fn round_up_pow2_32(v: i32) -> i32
pub fn round_up_pow2_64(v: i64) -> i64
pub fn quat_dot_quat(q1: Quaternion, q2: Quaternion) -> Float

New operators:

< impl PartialEq for Matrix4x4 {
< impl PartialEq for Transform {
< impl Add for Interval {
< impl Mul for Interval {
< impl Add for Quaternion {

New implementors (of a trait):

< impl Primitive for TransformedPrimitive {
< impl Primitive for BVHAccel {
< impl Light for InfiniteAreaLight {

New member functions (of an already existing struct):

> rg -B 19 -trust "fn corner"
src/lib.rs
2406-impl<T> Bounds3<T> {
...
2425:    pub fn corner(&self, corner: u8) -> Point3<T>

> rg -B 59 -trust "fn is_identity"
src/lib.rs
2873-impl Transform {
...
2932:    pub fn is_identity(&self) -> bool {

> rg -B 1 -trust "fn eval\("
src/lib.rs
3526-impl DerivativeTerm {
3527:    pub fn eval(&self, p: Point3f) -> Float {

> rg -B 833 -trust "fn interpolate"
src/lib.rs
3550-impl AnimatedTransform {
...
4383:    pub fn interpolate(&self, time: Float, t: &mut Transform) {

> rg -B 883 -trust "fn motion_bounds"
3550-impl AnimatedTransform {
...
4433:    pub fn motion_bounds(&self, b: Bounds3f) -> Bounds3f {

> rg -B 50 -trust "fn to_transform"
src/lib.rs
4628-impl Quaternion {
...
4678:    pub fn to_transform(&self) -> Transform {

> rg -trust "impl MipMap"
src/lib.rs
9931:impl MipMap {
...
10058:    pub fn width(&self) -> i32 {
...
10061:    pub fn height(&self) -> i32 {
...
10088:    pub fn lookup_pnt_flt(&self, st: &Point2f, width: Float) -> Spectrum {
...
10104:    pub fn lookup_pnt_vec_vec(&self, st: &Point2f, dst0: &mut Vector2f, dst1: &mut Vector2f) -> Spectrum {

> rg -trust "impl Distribution1D"
src/lib.rs
11137:impl Distribution1D {
...
11164:    pub fn count(&self) -> usize {
11167:    pub fn sample_continuous(&self, u: Float, pdf: Option<&mut Float>, off: Option<&mut usize>) -> Float {

> rg -trust "impl Distribution2D"
src/lib.rs
11251:impl Distribution2D {
...
11270:    pub fn sample_continuous(&self, u: &Point2f, pdf: &mut Float) -> Point2f {
...
11281:    pub fn pdf(&self, p: &Point2f) -> Float {

> rg -A 1 -trust "impl TransformSet"
src/lib.rs
12781:impl TransformSet {
12782-    pub fn is_animated(&self) -> bool {

Version 0.2.4 keeps the library in a single file with 13280 lines of code:

> wc lib.rs 
 13280  58238 504946 lib.rs

The first 857 lines are mainly used to create parts of the documentation and example code mentioned there. More examples are kept in a subdirectory (called examples) and the one file used to render the image above is called pest_test.rs. Version 0.2.4 consists of 86 public structs, 6 enums, 16 traits, and 110 public ""functions"":

> grep "^pub struct" lib.rs | wc
     86     345    2333
> grep "^pub enum" lib.rs | wc
      6      24     136
> grep "^pub trait" lib.rs | wc
     16      65     374
> grep "^pub fn" lib.rs | wc
    110     880    6228

v0.2.3

As mentioned in the last release I ran into a major bottleneck regarding building the BVH recursively. This releases fixes the problem. The art gallery scene builds it's BVH now in approx. 2 seconds (as opposed to 17 minutes before). All the details can be found here.

v0.2.2

While trying to render the following new scene ...

Art gallery rendered via Rust version of PBRT using direct lighting

... I ran into problems with the parser. The scene seemed to big and created a stack overflow. On the chat on gitter about pest I was told to update to pest = "^1.0.0-beta" (and pest_derive = "^1.0.0-beta") and it might go away. So, this is basically the main change of this release. The parser (in pest_test) had to be rewritten.

As you can see in the following image (which was rendered by the C++ version of PBRT), we still miss two textures (on the floor and the picture on the left wall):

Art gallery rendered via C++ version of PBRT using direct lighting

I also ran into serious delays after parsing the scene (and before rendering starts), where an acceleration structure is build. So I will focus on solving those problems in the next release. I assume that I need to implement the counterpart to the folowing C++ class, which deals with memory allocation:

> rg -tcpp "MemoryArena \{" ~/git/github/pbrt-v3/src -B 4 -A 3
/usr/people/jan/git/github/pbrt-v3/src/core/memory.h
58-class
59-#ifdef PBRT_HAVE_ALIGNAS
60-alignas(PBRT_L1_CACHE_LINE_SIZE)
61-#endif // PBRT_HAVE_ALIGNAS
62:    MemoryArena {
63-  public:
64-    // MemoryArena Public Methods
65-    MemoryArena(size_t blockSize = 262144) : blockSize(blockSize) {}

v0.2.1

I was so focused on getting path tracing working, that I didn't realize that the PBRT scene was actually flipped in x-direction. Version 0.2.1 can handle scale transformations, which I use to compensate for that:

Scale -1 1 1 # swap x-axis direction

Cornell Box scene rendered via Rust version of PBRT using path tracing (low settings)

I created also a new test scene, called simple room, which was originally a Radiance scene:

Simple room lit by a single light emitting sphere

What's missing in this release is to handle OpenEXR input textures, which could be used in conjunction with infinte light sources to simulate the effect of a sun&sky shader (which PBRT does not implement):

    LightSource "infinite"
        "integer samples" [ 4 ]
        "spectrum L" [ 2.0 2.0 ]
        "string mapname" "textures/baked_sky.exr"

The original scene uses such an outdoor lighting, which would be visible in the reflections of the crystal sphere.

The next new scene includes a cafe scene lit by two different set of lights:

Cafe scene - lighting variation one

Cafe scene - lighting variation two

v0.2.0

Version 0.2.0 can parse and render the Cornell Box scene correctly (with path tracing):

> ./target/release/examples/pest_test -i assets/scenes/cornell_box.pbrt
...
Writing image "pbrt.png" ...
done.

Low settings render in below 5 seconds:

Cornell Box scene rendered via Rust version of PBRT using path tracing (low settings)

Using higher settings creates a less noisy picture:

Cornell Box scene rendered via Rust version of PBRT using path tracing (low settings)

The changed settings can be seen in the diff output:

diff --git a/pbrt/assets/scenes/cornell_box.pbrt b/pbrt/assets/scenes/cornell_box.pbrt
index fcd79a6..4159b54 100644
--- a/pbrt/assets/scenes/cornell_box.pbrt
+++ b/pbrt/assets/scenes/cornell_box.pbrt
@@ -9,8 +9,9 @@ Film "image"
   "integer yresolution" [ 500 ]
 ##  "integer outlierrejection_k" [ 10 ]
 ##Sampler "sobol"
-Sampler "lowdiscrepancy" "integer pixelsamples" [8]
+Sampler "lowdiscrepancy" "integer pixelsamples" [512]
 ##PixelFilter "blackmanharris"
+PixelFilter "gaussian" "float xwidth" [2.000000 ] "float ywidth" [2.000000 ]
 ##SurfaceIntegrator "bidirectional"
 ##Integrator "directlighting" "integer maxdepth" [10]
 ##Integrator "ambientocclusion"

It also supports rendering ambient occlusion (AO):

Cornell Box scene rendered via Rust version of PBRT using ambient occlusion)

You have to change the following line to use the AOIntegrator:

Integrator "ambientocclusion"

v0.1.13

Version 0.1.13 can parse and render the Cornell Box scene correctly (with direct lighting):

> ./target/release/examples/pest_test -i assets/scenes/cornell_box.pbrt
...
Writing image "pbrt.png" ...
done.

Cornell Box scene rendered via Rust version of PBRT

The scene will later be used for global illumination.

The resulting image matches the C++ counterpart a hundred percent:

> imf_diff -d -f pbrt.png pbrt_cpp.png
pbrt.png pbrt_cpp.png: no differences.
== "pbrt.png" and "pbrt_cpp.png" are identical

The teapot scene matches, after fixing a bug in the ZeroTwoSequenceSampler, as well, beside a couple of pixels, probably due to the usage of HDR (OpenEXR) on the C++ side:

> imf_diff -d -f pbrt.png teapot-area-light.png diff.jpg
differing pixels:	  0.008% (5 of 65536)
average difference:	  0.907%
maximum difference:	  0.907%
Summary: 5 pixels differ slightly.
== "pbrt.png" and "teapot-area-light.png" are similar

v0.1.12

Version 0.1.12 can parse and render the teapot scene correctly:

> ./target/release/examples/pest_test -i assets/scenes/teapot-area-light.pbrt
...
Writing image "pbrt.png" ...
done.

Teapot scene rendered via Rust version of PBRT

If you compare that with the result rendered by the C++ version of PBRT:

Original teapot scene rendered via C++ version of PBRT

You will notice only minor differences. The problem is that we still use slightly different setting on the C++ side. I updated the scene description file so we use the same settings on the C++ side and the Rust side:

> diff teapot-area-light.pbrt teapot-area-light.pbrt.~90ae05b4d49cbbd900b8ef5f55be46f25de0557d~ 
8,11c8,9
< Integrator "directlighting" "integer maxdepth" [10]
< #Integrator "directlighting" 
< Sampler "lowdiscrepancy" "integer pixelsamples" [1]
< #Sampler "halton" "integer pixelsamples" [8]
---
> Integrator "directlighting" 
> Sampler "halton" "integer pixelsamples" [8]
13c11
< #Accelerator "kdtree"
---
> Accelerator "kdtree"

Now the resulting differences are only visible with false colors:

> imf_diff -d -f pbrt.png teapot-area-light.png diff.jpg
differing pixels:	  0.273% (179 of 65536)
average difference:	  4.640%
maximum difference:	 53.807%
Summary: Some pixels differ strongly.
== "pbrt.png" and "teapot-area-light.png" are different

Compare C++ version of PBRT cs. Rust version

v0.1.11

Version 0.1.11 can parse and render another provided test scenes now:

> ./target/release/examples/pest_test -i assets/scenes/teapot-area-light.pbrt
...
Writing image "pbrt.png" ...
done.

Teapot scene rendered via Rust version of PBRT

If you compare that with the result rendered by the C++ version of PBRT:

Original teapot scene rendered via C++ version of PBRT

You will notice that only the point light does illuminate the scene, but not the area light source emitted by the disk shape:

...
AttributeBegin
...
    AreaLightSource "area" "integer nsamples" [16 ] "color L" [8 8 8]
...
    Shape "disk" "float height" 0.000000 "float radius" 2.000000 
AttributeEnd
...
AttributeBegin
CoordSysTransform "camera"
LightSource "point" "color I" [ 50 50 50 ]
AttributeEnd
...

We also ignore the Sampler "halton" ... and Accelerator "kdtree"1 lines for now.

An interesting fact of this release is that we do avoid a fatal runtime error, a stack overflow, by spawning a thread with a bigger stack:

use std::thread;
...
fn main() {
    let child = thread::Builder::new().stack_size(32 * 1024 * 1024).spawn(move || {
...
    }).unwrap();
    let _res = child.join().unwrap();
}

The next release should illuminate this scene as well with the area light source.

v0.1.10

Version 0.1.10 can parse and render the first provided test scenes now:

> ./target/release/examples/pest_test -i assets/scenes/spheres-differentials-texfilt.pbrt
...
Writing image "pbrt.png" ...
done.

Same image as in version v0.1.6, but parsed from a PBRT scene description file

The second provided scene can be parsed but does not render (yet):

> ./target/release/examples/pest_test -i assets/scenes/example.pbrt
...
do something with created tokens ...
...
TODO: UVMapping2D
...
TODO: CreateDiskShape
...
WorldEnd
done.

The next release should either render that second test scene or provide another scene which renders.

v0.1.9

Version 0.1.9 can parse both provided test scenes now:

> ./target/release/examples/pest_test -i assets/scenes/example.pbrt
FILE = assets/scenes/example.pbrt
[Token { rule: statement, start: 0, end: 30 }, ...
... Token { rule: last_statement, start: 732, end: 741 }]
do something with created tokens ...
LookAt 0 10 100 0 -1 0 0 1 0
Camera "perspective" 
  "float fov" [30]
PixelFilter "mitchell" 
  "float xwidth" [2]
  "float ywidth" [2]
Sampler "halton" 
Film "image" 
  "integer xresolution" [200]
  "integer yresolution" [200]
  "string filename" ["simple.png"]
WorldBegin
AttributeBegin
CoordSysTransform "camera" 
LightSource "distant" 
  "point from" [0 0 0]
  "point to" [0 0 1]
  "rgb L" [3 3 3]
AttributeEnd
AttributeBegin
Rotate 135 1 0 0
Texture "checks" "spectrum" "checkerboard" 
  "float uscale" [4]
  "float vscale" [4]
  "rgb tex1" [1 0 0]
  "rgb tex2" [0 0 1]
Material "matte" 
  "texture Kd" "checks"
Shape "disk" 
  "float radius" [20]
  "float height" [-1]
AttributeEnd
WorldEnd
done.

The second scene should render in the next release after parsing the scene description:

> ./target/release/examples/pest_test -i assets/scenes/spheres-differentials-texfilt.pbrt
FILE = assets/scenes/spheres-differentials-texfilt.pbrt
[Token { rule: statement, start: 1, end: 29 }, ...
... Token { rule: last_statement, start: 1070, end: 1079 }]
do something with created tokens ...
LookAt 2 2 5 0 -0.4 0 0 1 0
Camera "perspective" 
  "float fov" [30]
Film "image" 
  "integer xresolution" [1000]
  "integer yresolution" [500]
  "string filename" ["spheres-differentials-texfilt.exr"]
Integrator "directlighting" 
  "integer maxdepth" [10]
Sampler "lowdiscrepancy" 
  "integer pixelsamples" [1]
PixelFilter "box" 
WorldBegin
LightSource "distant" 
  "point from" [0 10 0]
  "point to" [0 0 0]
  "rgb L" [3.141593 3.141593 3.141593]
AttributeBegin
Translate 0.25 0 0
Texture "checker" "color" "checkerboard" 
  "vector v1" [1 0 0]
  "vector v2" [0 0 1]
  "string mapping" ["planar"]
  "string aamode" ["none"]
Texture "lines-tex" "color" "imagemap" 
  "float uscale" [100]
  "float vscale" [100]
  "string filename" ["textures/lines.png"]
Material "matte" 
  "texture Kd" "lines-tex"
Shape "trianglemesh" 
  "integer indices" [ 0 2 1 0 3 2 ]
  "float st" [ 0 0 1 0 0 1 1 1 ]
  "point P" [
    -100 -1 -100 
    400 -1 -100 
    400 -1 400 
    -100 -1 400 
  ]
AttributeEnd
Translate -1.3 0 0
Material "mirror" 
Shape "sphere" 
Translate 2.6 0 0
Material "glass" 
Shape "sphere" 
WorldEnd
done.

v0.1.8

Version 0.1.8 still keeps the library in a single file with 9725 lines of code:

> wc lib.rs 
  9725  42500 362833 lib.rs

The first 613 lines are mainly used to create parts of the documentation and example code mentioned there. More examples are kept in a subdirectory (called examples).

Version 0.1.8 consists of 73 public structs, 6 enums, 12 traits, and 86 public ""functions"":

> grep "^pub struct" lib.rs | wc
     73     293    1943
> grep "^pub enum" lib.rs | wc
      6      24     136
> grep "^pub trait" lib.rs | wc
     12      49     281
> grep "^pub fn" lib.rs | wc
     86     709    4934

This version still renders the images shown below, via an example, which generates a scene and gives you a couple of options how to render the scene:

> cargo test --release
> ./target/release/examples/pbrt_spheres_differentials_texfilt -h
Usage: ./target/release/examples/pbrt_spheres_differentials_texfilt [options]

Options:
    -h, --help          print this help menu
    -c, --checker       use procedural texture
    -i, --image         use image texture
    -n, --none          use no texture
    -m, --matte         use only matte materials
    -v, --version       print version number

There is another example program which can render a teapot scene with 2328 triangles:

Teapot scene rendered via Rust version of PBRT

But I removed the Rust code which generates most of the triangles and checked in only a version with the ground plane triangles. The reason is that the resulting 120k lines of Rust code take several minutes to compile.

Therefore I started to work on issue #3 and invested some time to investigate, if I could use a crate called pest to write a parser for the scene description. The current example code has a help message, which tells you how to parse an input file:

> ./target/release/examples/pest_test -h
Usage: ./target/release/examples/pest_test [options]

Options:
    -h, --help          print this help menu
    -i FILE             parse an input file
    -v, --version       print version number

Warning: If you want to compile the pest_test executable you need to download and compile with Rust nightly:

rustup install nightly
rustup default nightly

If you run the example executable with one of the provided examples (currently only one works), you will see that tokens get generated:

> ./target/release/examples/pest_test -i assets/scenes/pest_test.pbrt
FILE = assets/scenes/pest_test.pbrt
[Token { rule: statement, start: 0, end: 30 }, Token { rule: look_at, start: 0, end: 30 }, ...
Token { rule: last_statement, start: 732, end: 740 }]
do something with created tokens ...
LookAt 0 10 100 0 -1 0 0 1 0

Camera "perspective"
  "float fov" [30]

PixelFilter "mitchell"
  "float xwidth" [2]
  "float ywidth" [2]

Sampler "halton"


Film "image"
  "integer xresolution" [200]
  "integer yresolution" [200]
  "string filename" ["simple.png"]
WorldBegin
AttributeBegin
CoordSysTransform "camera"

LightSource "distant"
  "point from" [0 0 0]
  "point to" [0 0 1]
  "rgb L" [3 3 3]
AttributeEnd
AttributeBegin
Rotate 135 1 0 0

Texture "checks" "spectrum" "checkerboard"
  "float uscale" [4]
  "float vscale" [4]
  "rgb tex1" [1 0 0]
  "rgb tex2" [0 0 1]

Material "matte"
  "texture Kd" "checks"

Shape "disk"
  "float radius" [20]
  "float height" [-1]
AttributeEnd
WorldEnd
done.

The tokens are then used to print the read information in a slightly different formating to prove that all read information is ready to be used in API calls to actually generate geometry and render a parsed scene description. I have to work on that API next and the parser has to be changed to parse more scene description files. I would say if it can parse the scene file used for the previous images I call it another release.

v0.1.7

Version v0.1.7 renders the same image as v0.1.6 using all available CPUs.

v0.1.6

Scene with a glass material on the first sphere and a mirror material on the second sphere. The ground triangles use a texture on a matte material. Rendered via the Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

v0.1.5

Scene with a glass material on the first sphere and a mirror material on the second sphere. The ground triangles use a procedural checker texture on a matte material. Rendered via the Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

v0.1.4

Scene with a glass material on the first sphere and a mirror material on the second sphere, rendered via Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

The scene should render correctly now (using matte, mirror, and glass materials).

  • New structs: SpecularTransmission (implementing Bxdf trait), TrowbridgeReitzDistribution
  • New functions: nrm_faceforward_vec3(), refract(), fr_dielectric(), GlassMaterial::bsdf(), DirectLightingIntegrator::specular_transmit()
  • New operators: RGBSpectrum::operator-
  • New parameters: GlassMaterial::remap_roughness
  • Changed signature of trait function Fresnel::evaluate()
  • impl Fresnel for FresnelDielectric
  • New fresnel parameter in constructor of SpecularReflection
  • #[derive(PartialEq)] for TransportMode

v0.1.3

Scene with a mirror material on the second sphere, rendered via Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

The scene should render correctly now (using matte and mirror materials).

  • Implemented MirrorMaterial::compute_scattering_functions()
  • MirrorMaterial::bsdf()
  • New struct SpecularReflection (implementing f(), sample_f(), and get_type() for Bxdf trait)
  • New trait Fresnel with Fresnel::evaluate()
  • New struct FresnelNoOp implementing Fresnel::evaluate()
  • Bxdf::sample_f()
  • LambertianReflection::sample_f() and OrenNayar::sample_f()
  • Bsdf::components(), Bsdf::local_to_world(), and Bsdf::sample_f()
  • SurfaceInteraction::spawn_ray()
  • New functions cosine_sample_hemisphere() and concentric_sample_disk()
  • operator+ and operator* on Normal3<T>
  • operator[] on Point2<T>
  • New constants: PI_OVER_2 and PI_OVER_4
  • New utility function cos_theta()

v0.1.2

Correct picture for matte material rendered via Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

The scene should render correctly now (using only matte materials).

  • Sphere::phi_max in radians
  • implemented Transform::transform_surface_interaction()
  • implemented Transform::transform_normal()
  • implemented Transform::transform_point_with_abs_error()
  • changed 'struct Shading' to use some normals instead of vectors
  • added vec3_abs_dot_nrm()
  • renamed vec3_cross() to vec3_cross_vec3()
  • impl Neg for Normal3
  • impl Div for Normal3
  • added nrm_cross_vec3()
  • added nrm_normalize()
  • added nrm_dot_nrm()
  • added nrm_faceforward_nrm()

v0.1.1

Improved picture rendered via Rust version of PBRT:

Improved picture rendered via Rust version of PBRT

Basically the black spots on the ground of the test scene are gone now.

  • fixed bug in DistantLight::sample_li()
  • switched to f32 for Float
  • fixed get_1d()
  • calculate ray.time via lerp()
  • fixed some precision issues
  • corrected absolute error for transformed point
  • use double precision in vec3_cross()
  • implement division by multiplying with inverse
  • normalizing vectors

v0.1.0

First picture rendered via Rust version of PBRT:

First picture rendered via Rust version of PBRT

The original scene, rendered by the C++ version of PBRT, can be seen here.

Version 0.1.0 keeps the library in a single file with 7173 lines of code:

> wc lib.rs 
  7173  31925 268293 lib.rs

The first 613 lines are mainly used to create parts of the documentation and example code mentioned there. More examples are kept in a subdirectory (called examples) and the one file used to render the image above is called pbrt_spheres_differentials_texfilt.rs. Version 0.1.0 consists of 51 public structs, 5 enums, 5 traits, and 61 public functions:

> grep "^pub struct" lib.rs | wc
     51     204    1302
> grep "^pub enum" lib.rs | wc
      5      20     115
> grep "^pub trait" lib.rs | wc
      5      20     108
> grep "^pub fn" lib.rs | wc
     61     500    3549