Jan Walter September 05, 2023 [TRACE] #rs_pbrt #pbrt-v4 #pbrt-v3 #tev
iXialumy discussed (a while ago) with
me how to connect rs-pbrt to the image
viewer tev (while rendering) and made
a pull request about it,
pretty much the same way pbrt-v4
does it (see
video). For a long time
I had not much time to spend on rs_pbrt
and only updated the
dependencies and made minor code changes. Yesterday I finally took the
time to look at his solution and created a tev
branch on the main
repository on
sourcehut
(the github and
codeberg repositories are more or
less just mirrors with their own capability to create issues
and
pull requests
). In contrast to pbrt-v4
the current solution
renders still in buckets (which means the part of the image gets
visible in tev
only once all samples for those pixels are
calculated), whereas pbrt-v4
renders a full resolution noisy image
first and converges to a less noisy image while more and more samples
are computed:
You should be able to clone
the repository (read-only
) either by:
$ git clone https://git.sr.ht/~wahn/rs-pbrt
Cloning into 'rs-pbrt'...
...
Or (a read/write
version) by:
$ git clone git@git.sr.ht:~wahn/rs-pbrt
Cloning into 'rs-pbrt'...
...
To use the tev
branch you must figure out that there is a remote
branch of that name and then locally checkout
that branch.
$ git branch
* master
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/tev
$ git checkout tev
branch 'tev' set up to track 'origin/tev'.
Switched to a new branch 'tev'
$ git branch
master
* tev
If you want to compile two versions (one for the tev
branch and one
for the master
branch) and compile the version information into the
executables you can do the following:
$ git describe --tags
v0.9.10-1-gccda035
$ export GIT_DESCRIBE="v0.9.10-1-gccda035"
$ make
...
$ mv target/ target_tev
$ ./target_tev/release/rs_pbrt -h | head -n 1
rs_pbrt version 0.9.10 (v0.9.10-1-gccda035) [Detected 28 cores]
And the same for the master
branch:
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ git branch
* master
tev
$ git describe --tags
v0.9.10
$ export GIT_DESCRIBE="v0.9.10"
$ make
...
$ mv target/ target_master
$ ./target_master/release/rs_pbrt -h | head -n 1
rs_pbrt version 0.9.10 (v0.9.10) [Detected 28 cores]
If you pipe the output of rs_pbrt -h
into two text files and compare
them, you will see that there is a new option now to connect to the
display server (or better tev
):
$ diff -b rs_pbrt_tev.txt rs_pbrt_master.txt
1c1
< rs_pbrt version 0.9.10 (v0.9.10-1-gccda035) [Detected 28 cores]
---
> rs_pbrt version 0.9.10 (v0.9.10) [Detected 28 cores]
16d15
< --display-server <DISPLAY_SERVER> The address and port of the display server
The full command used in the screenshot above was:
$ time /media/datadisk3/git/sourcehut/rs-pbrt/target_tev/release/rs_pbrt --display-server localhost:14158 --path ganesha.pbrt
...
real 1m32,956s
user 35m11,823s
sys 0m3,643s
The C++
version of pbrt-v3 should
be slightly faster than the Rust
version:
$ pwd
/media/datadisk3/Graphics/Rendering/PBRT/pbrt-v3-scenes/ganesha
$ time /media/datadisk3/git/github/pbrt-v3/build/pbrt ganesha.pbrt
pbrt version 3 (built Sep 5 2023 at 12:37:06) [Detected 28 cores]
Copyright (c)1998-2018 Matt Pharr, Greg Humphreys, and Wenzel Jakob.
The source code to pbrt (but *not* the book contents) is covered by the BSD License.
See the file LICENSE.txt for the conditions of the license.
Rendering: [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++] (61.5s)
Statistics:
BVH
Interior nodes 3648372
Leaf nodes 3648373
Primitives per leaf node 4323664 / 3648373 (1.19x)
Integrator
Camera rays traced 268378112
Path length 1.316 avg [range 0 - 4]
Zero-radiance paths 146856926 / 353774467 (41.51%)
Intersections
Regular ray intersection tests 680824749
Shadow ray intersection tests 217814691
Ray-triangle intersection tests 435722899 / 3289961203 (13.24%)
Memory
BVH tree 288.65 MiB
Film pixels 15.82 MiB
Primitives 296.88 MiB
Texture MIP maps 257.00 MiB
TransformCache 260.00 kB
Triangle meshes 385.41 MiB
Scene
AreaLights 4
Lights 5
Materials created 1
Shapes created 4323664
Probes per TransformCache lookup 1.000 avg [range 1 - 1]
TransformCache hits 8 / 10 (80.00%)
Triangles per triangle mesh 4323664 / 4 (1080916.00x)
SpatialLightDistribution
Distributions created 4212
Hash probes per lookup 1.002 avg [range 1 - 3]
Lookups per distribution 353774467 / 4212 (83992.04x)
Texture
EWA lookups 162214764
Trilinear lookups 145501962
Profile
Integrator::Render() 96.62% ( 0:01:06.63)
Camera::GenerateRay[Differential]() 2.12% ( 0:00:01.46)
Film::AddSample() 3.27% ( 0:00:02.25)
Film::MergeTile() 0.00% ( 0:00:00.00)
Sampler::GetSample[12]D() 4.88% ( 0:00:03.36)
Sampler::StartPixelSample() 0.00% ( 0:00:00.00)
SamplerIntegrator::Li() 84.30% ( 0:00:58.13)
Accelerator::Intersect() 36.19% ( 0:00:24.96)
Triangle::Intersect() 8.14% ( 0:00:05.61)
BSDF::Sample_f() 3.15% ( 0:00:02.16)
Direct lighting 33.99% ( 0:00:23.44)
Accelerator::Intersect() 3.77% ( 0:00:02.60)
Triangle::Intersect() 0.74% ( 0:00:00.51)
Accelerator::IntersectP() 12.32% ( 0:00:08.49)
Triangle::IntersectP() 2.36% ( 0:00:01.62)
BSDF::PDF() 0.71% ( 0:00:00.48)
BSDF::Sample_f() 3.31% ( 0:00:02.28)
BSDF::f() 0.59% ( 0:00:00.40)
Light::Pdf() 2.10% ( 0:00:01.45)
Triangle::Intersect() 0.86% ( 0:00:00.59)
Light::Sample_*() 2.93% ( 0:00:02.02)
MIPMap::Lookup() (trilinear) 0.55% ( 0:00:00.38)
MIPMap::Lookup() (trilinear) 0.26% ( 0:00:00.18)
Sampler::GetSample[12]D() 3.99% ( 0:00:02.74)
MIPMap::Lookup() (trilinear) 0.87% ( 0:00:00.60)
Material::ComputeScatteringFunctions() 3.20% ( 0:00:02.20)
MIPMap::Lookup() (EWA) 2.21% ( 0:00:01.52)
Sampler::GetSample[12]D() 1.69% ( 0:00:01.16)
SpatialLightDistribution lookup 0.77% ( 0:00:00.52)
SpatialLightDistribution creation 0.03% ( 0:00:00.02)
Light::Sample_*() 0.02% ( 0:00:00.01)
MIPMap::Lookup() (trilinear) 0.01% ( 0:00:00.00)
Scene parsing and creation 3.38% ( 0:00:02.33)
Acceleration structure creation 1.56% ( 0:00:01.07)
MIPMap::Lookup() (trilinear) 0.00% ( 0:00:00.00)
Texture loading 0.77% ( 0:00:00.52)
MIP map generation 0.37% ( 0:00:00.25)
Profile (flattened)
Accelerator::Intersect() 31.09% ( 0:00:21.43)
Sampler::GetSample[12]D() 10.55% ( 0:00:07.27)
Accelerator::IntersectP() 9.96% ( 0:00:06.86)
Triangle::Intersect() 9.74% ( 0:00:06.71)
BSDF::Sample_f() 6.45% ( 0:00:04.44)
SamplerIntegrator::Li() 4.44% ( 0:00:03.06)
Direct lighting 4.01% ( 0:00:02.76)
Film::AddSample() 3.27% ( 0:00:02.25)
Light::Sample_*() 2.39% ( 0:00:01.65)
Triangle::IntersectP() 2.36% ( 0:00:01.62)
MIPMap::Lookup() (EWA) 2.21% ( 0:00:01.52)
Camera::GenerateRay[Differential]() 2.12% ( 0:00:01.46)
Integrator::Render() 2.04% ( 0:00:01.40)
MIPMap::Lookup() (trilinear) 1.70% ( 0:00:01.17)
Acceleration structure creation 1.56% ( 0:00:01.07)
Light::Pdf() 1.25% ( 0:00:00.85)
Scene parsing and creation 1.06% ( 0:00:00.72)
Material::ComputeScatteringFunctions() 0.99% ( 0:00:00.68)
SpatialLightDistribution lookup 0.74% ( 0:00:00.50)
BSDF::PDF() 0.71% ( 0:00:00.48)
BSDF::f() 0.59% ( 0:00:00.40)
Texture loading 0.40% ( 0:00:00.27)
MIP map generation 0.37% ( 0:00:00.25)
SpatialLightDistribution creation 0.01% ( 0:00:00.00)
Film::MergeTile() 0.00% ( 0:00:00.00)
Sampler::StartPixelSample() 0.00% ( 0:00:00.00)
real 1m9,062s
user 28m15,524s
sys 0m1,292s
Because rs_pbrt
renders currently to a
PNG file (pbrt.png
) and the C++
version of pbrt-v3
to an OpenEXR
file, we have to convert the image first before we can compare both
images:
$ /media/datadisk3/git/github/pbrt-v4/build/imgtool convert ganesha.exr --outfile ganesha_pbrt_v3.png
$ imf_diff ganesha_pbrt_v3.png /media/datadisk3/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_ganesha/pbrt.png
differing pixels: 0.004% (21 of 518400)
average difference: 1.674%
maximum difference: 3.069%
Summary: A few pixels differ slightly.
== "ganesha_pbrt_v3.png" and "/media/datadisk3/git/gitlab/rs-pbrt-test-scenes/pbrt/pbrt_ganesha/pbrt.png" are similar
There was a time where the Rust version was rendering both a PNG
and an OpenEXR file, but currently this is disabled, I might bring
that back one day (after I adjusted the code to the latest
openexr crate).
Anyway, the ganesha
scene renders slightly different for pbrt-v4
(so either the material or the color correction is differently
implemented).
$ time /media/datadisk3/git/github/pbrt-v4/build/pbrt --display-server localhost:14158 ganesha.pbrt
pbrt version 4 (built Sep 5 2023 at 12:50:51)
Copyright (c)1998-2021 Matt Pharr, Wenzel Jakob, and Greg Humphreys.
The source code to pbrt (but *not* the book contents) is covered by the Apache 2.0 License.
See the file LICENSE.txt for the conditions of the license.
Rendering: [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++] (80.9s)
real 1m26,190s
user 37m28,375s
sys 0m1,449s
So the C++ version of pbrt-v4
is slower than the previous pbrt-v3
C++ version (but renders in a similar time to the Rust
implementation), using the CPUs
, but as soon as you enable the GPU
things get fast (depends on your graphics card):
$ time /media/datadisk3/git/github/pbrt-v4/build/pbrt --display-server localhost:14158 --gpu ganesha.pbrt
pbrt version 4 (built Sep 5 2023 at 12:50:51)
Copyright (c)1998-2021 Matt Pharr, Wenzel Jakob, and Greg Humphreys.
The source code to pbrt (but *not* the book contents) is covered by the Apache 2.0 License.
See the file LICENSE.txt for the conditions of the license.
Rendering: [+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++] (6.5s)
real 0m9,541s
user 0m11,811s
sys 0m2,107s
To compare both images (rendered on the CPU vs. the GPU) you can
select both images within tev
and select a couple of buttons (E
for Error, AE
for Absolute Error, SE
for Squared
Error, RAE
for Relative Absolute Error, and RSE
for
Relative Squared Error):
You can also compare both images via the imf_diff
tool:
$ imf_diff -d -f ganesha_?pu.exr ganesha_diff.jpg
differing pixels: 11.242% (58281 of 518400)
average difference: 1.520%
maximum difference: 9.705%
Summary: Many pixels differ slightly.
== "ganesha_cpu.exr" and "ganesha_gpu.exr" are different
Currently the connection to tev
works for the Rust renderer
rs_pbrt
only for the integrators which use the
SamplerIntegrator
render loop. This will most likely be changed soon and before the
tev
branch gets merged into the master
branch.
Finally, I was interested how to watch the GPUs rendering (on Linux)
and found a command line tool, called nvtop
(NVIDIA GPU top):
Back to top