Cornell Box denoised

Jan Walter November 11, 2023 [TRACE] #arnold #denoise #pbrt-v4

Let's talk about denoising in general before we go into some details how this might be handled by various renderers. We will use the famous Cornell Box for a start. If someone can't wait to get started or is too lazy to learn how to model such a simple scene in any DCC I do provide a Blender 2.79 scene (should still work on older computers) for convenience:

Blender 2.79 scene rendered by Cycles with denoising

Just press the render button (F12) and watch the Cycles renderer doing it's job.

Cycles' denoising settings

I do recommend though to try at least once to model this simple scene in any DCC by just using the provided data.

Arnold

For Arnold I described the details already in Denoising with Arnold. Therefore here the short version:

$ more Makefile
ARNOLD = /usr/local/Arnold
KICK = $(ARNOLD)/bin/kick
NOICE = $(ARNOLD)/bin/noice
EXR = arnold.exr noice.exr

all: render

clean:
	-rm -f *~

clobber: clean
	-rm -f $(EXR)

render: cornell_box_denoise.ass
	$(KICK) -dp -dw -i cornell_box_denoise.ass -v 6
	$(NOICE) -i arnold.exr -o noice.exr

A Makefile (see above) can be used to first call kick (to render several AOVs into an OpenEXR file called arnold.exr) and then noice (to use those AOVs to create a less noisy image called noice.exr).

Original vs. denoised version rendered by Arnold

The full log can be seen here:

$ make
/usr/local/Arnold/bin/kick -dp -dw -i cornell_box_denoise.ass -v 6
00:00:00   114MB         | log started Sat Nov 11 15:42:16 2023
00:00:00   114MB         | Arnold 7.2.4.1 [1fee86c4] linux x86_64 clang-15.0.7 oiio-2.4.1 osl-1.12.9 vdb-7.1.1 adlsdk-7.4.2.47 clmhub-3.1.1.43 rlm-14.2.5 optix-6.6.0 2023/10/17 03:09:19
00:00:00   114MB         | running on tuxedo-desktop, pid=28827
00:00:00   114MB         |  1 x Intel(R) Core(TM) i9-9940X CPU @ 3.30GHz (14 cores, 28 logical) with 128488MB
00:00:00   126MB         |  NVIDIA driver version 535.54 (Optix 60806)
00:00:00   126MB         |  GPU 0: NVIDIA GeForce RTX 2080 Ti @ 1545MHz (compute 7.5) with 11011MB (11002MB available) (NVLink:0)
00:00:00   126MB         |  GPU 1: NVIDIA GeForce RTX 2080 Ti @ 1545MHz (compute 7.5) with 11003MB (10464MB available) (NVLink:0)
00:00:00   126MB         |  Ubuntu 22.04.2 LTS (Jammy Jellyfish), Linux kernel 5.15.0-76-generic
00:00:00   126MB         |  soft limit for open files is set at 1048574
00:00:00   126MB         |  
00:00:00   127MB         | [color_manager_ocio] default ocio.config found in /media/datadisk3/local/Arnold-7.2.4.1/bin/../ocio/configs/arnold/config.ocio
00:00:00   127MB         | loading plugins from /media/datadisk3/local/Arnold-7.2.4.1/bin/../plugins ...
00:00:00   128MB         |  cryptomatte.so: cryptomatte uses Arnold 7.2.4.1
00:00:00   128MB         |  cryptomatte.so: cryptomatte_filter uses Arnold 7.2.4.1
00:00:00   128MB         |  cryptomatte.so: cryptomatte_manifest_driver uses Arnold 7.2.4.1
00:00:00   128MB         |  alembic_proc.so: alembic uses Arnold 7.2.4.1
00:00:00   128MB         |  usd_proc.so: usd uses Arnold 7.2.4.1
00:00:00   128MB         | loaded 5 plugins from 3 lib(s) in 0:00.00
00:00:00   128MB         | [color_manager_ocio] default ocio.config found in /media/datadisk3/local/Arnold-7.2.4.1/bin/../ocio/configs/arnold/config.ocio
00:00:00   129MB         | [kick] command: /usr/local/Arnold/bin/kick -dp -dw -i cornell_box_denoise.ass -v 6
00:00:00   129MB         | loading plugins from . ...
00:00:00   129MB         | no plugins loaded
00:00:00   131MB         | [metadata] loading metadata file: cornell_box_denoise.ass
00:00:00   132MB         | [ass] loading cornell_box_denoise.ass ...
00:00:00   132MB         | [ass] read 4425 bytes, 16 nodes in 0:00.00
00:00:00   132MB         | 
00:00:00   132MB         | authorizing with license manager: user ...
00:00:00   135MB         | [user] authorized user "jdb.walter3QDPU" in 0:00.42
00:00:00   135MB         | [user] expiration date: 2024-06-11T11:58:47+02:00
00:00:00   135MB         | 
00:00:00   135MB         | [color_manager] using color manager of type "color_manager_ocio"
00:00:00   136MB         | [color_manager_ocio] using config file /media/datadisk3/local/Arnold-7.2.4.1/bin/../ocio/configs/arnold/config.ocio
00:00:00   137MB         | [color_manager] rendering color space is "ACEScg"
00:00:00   186MB         |  
00:00:00   186MB         | there are 1 light and 5 objects:
00:00:00   186MB         |       1 persp_camera
00:00:00   186MB         |       1 mesh_light
00:00:00   186MB         |       1 ray_switch_rgba
00:00:00   186MB         |       2 utility
00:00:00   186MB         |       5 standard_surface
00:00:00   186MB         |       1 driver_exr
00:00:00   186MB         |       2 box_filter
00:00:00   186MB         |       1 gaussian_filter
00:00:00   186MB         |       1 variance_filter
00:00:00   186MB         |       4 polymesh
00:00:00   186MB         |       2 list_aggregate
00:00:00   186MB         |       2 color_manager_ocio
00:00:00   186MB         |  
00:00:00   186MB         | rendering image at 500 x 500, 5 AA samples
00:00:00   186MB         |   AA samples max    <disabled>
00:00:00   186MB         |   AA sample clamp   <disabled>
00:00:00   186MB         |   diffuse           samples  1 / depth  3
00:00:00   186MB         |   specular          samples  3 / depth  1
00:00:00   186MB         |   transmission      samples  3 / depth  6
00:00:00   186MB         |   volume indirect   <disabled by depth>
00:00:00   186MB         |   total                          depth 12
00:00:00   186MB         |   bssrdf            samples  2
00:00:00   186MB         |   light             <using per light samples>
00:00:00   186MB         |   transparency      depth 10
00:00:00   186MB         | initializing 20 nodes
00:00:00   186MB         |  creating root object list ...
00:00:00   186MB         | node initialization done in 0:00.00 (multithreaded)
00:00:00   186MB         | updating 21 nodes
00:00:00   187MB         |  MALight_light: mesh_light using 3 samples, 2 volume samples
00:00:00   187MB         |  scene bounds: (-0.556000113 -1.49375722e-07 0) -> (7.79891695e-15 0.559200048 0.548800051)
00:00:00   187MB         | node update done in 0:00.00 (multithreaded)
00:00:00   188MB         | [aov] parsing 8 output statements ...
00:00:00   188MB         | [aov] registered driver: "driver" (driver_exr)
00:00:00   188MB         | [aov]  * "RGBA" of type RGBA filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "emission" of type RGB filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "diffuse_direct" of type RGB filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "diffuse_indirect" of type RGB filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "RGBA" of type RGBA filtered by "variance_filter" (variance_filter)
00:00:00   188MB         | [aov]  * "diffuse_albedo" of type RGB filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "Z" of type FLOAT filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov]  * "N" of type VECTOR filtered by "filter" (gaussian_filter)
00:00:00   188MB         | [aov] done preparing 8 AOVs for 8 outputs to 1 driver (0 deep AOVs)
00:00:00   214MB         | starting 28 bucket workers of size 32x32 ...
00:00:00   249MB         |  [accel] list_aggregate bvh4 done - 0:00.00 (wall time) - 4 prims, 1 key
00:00:00   250MB         |  [accel] polymesh bvh4 done - 0:00.00 (wall time) - 5 prims, 1 key
00:00:00   253MB         |  [accel] polymesh bvh4 done - 0:00.00 (wall time) - 6 prims, 1 key
00:00:00   258MB         |  [accel] polymesh bvh4 done - 0:00.00 (wall time) - 6 prims, 1 key
00:00:00   280MB         |    1% done - 75 rays/pixel
00:00:01   282MB         |    5% done - 113 rays/pixel
00:00:01   282MB         |   10% done - 307 rays/pixel
00:00:01   284MB         |   15% done - 559 rays/pixel
00:00:01   286MB         |   20% done - 215 rays/pixel
00:00:02   288MB         |   25% done - 322 rays/pixel
00:00:02   290MB         |   30% done - 301 rays/pixel
00:00:02   291MB         |   35% done - 171 rays/pixel
00:00:02   292MB         |   40% done - 427 rays/pixel
00:00:02   293MB         |   45% done - 157 rays/pixel
00:00:03   293MB         |   50% done - 207 rays/pixel
00:00:03   293MB         |   55% done - 177 rays/pixel
00:00:03   294MB         |   60% done - 149 rays/pixel
00:00:03   294MB         |   65% done - 287 rays/pixel
00:00:03   295MB         |   70% done - 374 rays/pixel
00:00:04   296MB         |   75% done - 222 rays/pixel
00:00:04   297MB         |   80% done - 513 rays/pixel
00:00:04   297MB         |   85% done - 168 rays/pixel
00:00:04   298MB         |   90% done - 170 rays/pixel
00:00:04   298MB         |   95% done - 94 rays/pixel
00:00:04   298MB         |  100% done - 80 rays/pixel
00:00:04   298MB         | render done in 0:04.321
00:00:04   298MB         | [driver_exr] writing file `arnold.exr'
00:00:04   298MB         | render done
00:00:04   298MB         |  
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | scene creation time          0:00.03    machine utilization (1.29%) 
00:00:04   298MB         |  unaccounted                 0:00.03 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | frame time                   0:04.88    machine utilization (86.92%) 
00:00:04   298MB         |  driver init/close           0:00.02 
00:00:04   298MB         |  rendering                   0:04.32 
00:00:04   298MB         |   output driver              0:00.02 
00:00:04   298MB         |   pixel rendering            0:04.29 
00:00:04   298MB         |  unaccounted                 0:00.53 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | top session self-times by category 
00:00:04   298MB         |  LightSampling (MALight_light)                                      0:00.77 (18.00%) 
00:00:04   298MB         |  accumulateBucketSamples                                            0:00.67 (15.53%) 
00:00:04   298MB         |  polymesh::intersect                                                0:00.66 (15.30%) 
00:00:04   298MB         |   MEcornell_box                                                     0:00.58 (13.45%) 
00:00:04   298MB         |   MElarge_box                                                       0:00.03 ( 0.71%) 
00:00:04   298MB         |   MELight                                                           0:00.02 ( 0.61%) 
00:00:04   298MB         |   MEsmall_box                                                       0:00.02 ( 0.53%) 
00:00:04   298MB         |  surface closure                                                    0:00.64 (14.86%) 
00:00:04   298MB         |   MAcbox_Material                                                   0:00.30 ( 7.04%) 
g00:00:04   298MB         |   MAbox_Material                                                    0:00.11 ( 2.72%) 
00:00:04   298MB         |   MAcbox_red                                                        0:00.11 ( 2.56%) 
00:00:04   298MB         |   MAcbox_green                                                      0:00.10 ( 2.53%) 
00:00:04   298MB         |  BVH::intersect                                                     0:00.33 ( 7.81%) 
00:00:04   298MB         |   root                                                              0:00.23 ( 5.55%) 
00:00:04   298MB         |   MEcornell_box                                                     0:00.08 ( 1.87%) 
00:00:04   298MB         |  AiLightsPrepare                                                    0:00.29 ( 6.85%) 
00:00:04   298MB         |   MEcornell_box                                                     0:00.25 ( 5.85%) 
00:00:04   298MB         |   MElarge_box                                                       0:00.03 ( 0.78%) 
00:00:04   298MB         |  TraceCameraRay                                                     0:00.18 ( 4.38%) 
00:00:04   298MB         |  ray traversal+intersection                                         0:00.13 ( 3.20%) 
00:00:04   298MB         |  TraceShadow                                                        0:00.11 ( 2.62%) 
00:00:04   298MB         |  sampleNextBatch                                                    0:00.11 ( 2.57%) 
00:00:04   298MB         |  processBucketSamples                                               0:00.11 ( 2.55%) 
00:00:04   298MB         |  standard_surface                                                   0:00.09 ( 2.27%) 
00:00:04   298MB         |   MAcbox_Material                                                   0:00.05 ( 1.20%) 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | top session self-times by node 
00:00:04   298MB         |  mesh_light:MALight_light                                           0:00.98 (22.84%) 
00:00:04   298MB         |   LightSampling                                                     0:00.77 (18.00%) 
00:00:04   298MB         |   TraceShadow                                                       0:00.11 ( 2.60%) 
00:00:04   298MB         |   ray traversal+intersection                                        0:00.09 ( 2.24%) 
00:00:04   298MB         |  polymesh:MEcornell_box                                             0:00.91 (21.19%) 
00:00:04   298MB         |   polymesh::intersect                                               0:00.58 (13.45%) 
00:00:04   298MB         |   AiLightsPrepare                                                   0:00.25 ( 5.85%) 
00:00:04   298MB         |   BVH::intersect                                                    0:00.08 ( 1.87%) 
00:00:04   298MB         |  accumulateBucketSamples                                            0:00.67 (15.53%) 
00:00:04   298MB         |  standard_surface:MAcbox_Material                                   0:00.42 ( 9.83%) 
00:00:04   298MB         |   surface closure                                                   0:00.30 ( 7.04%) 
00:00:04   298MB         |   AiLightsTrace                                                     0:00.03 ( 0.72%) 
00:00:04   298MB         |  list_aggregate:root (BVH::intersect)                               0:00.23 ( 5.55%) 
00:00:04   298MB         |  TraceCameraRay                                                     0:00.18 ( 4.38%) 
00:00:04   298MB         |  standard_surface:MAbox_Material                                    0:00.16 ( 3.73%) 
00:00:04   298MB         |   surface closure                                                   0:00.11 ( 2.72%) 
00:00:04   298MB         |  standard_surface:MAcbox_red                                        0:00.14 ( 3.46%) 
00:00:04   298MB         |   surface closure                                                   0:00.11 ( 2.56%) 
00:00:04   298MB         |  standard_surface:MAcbox_green                                      0:00.14 ( 3.37%) 
00:00:04   298MB         |   surface closure                                                   0:00.10 ( 2.53%) 
00:00:04   298MB         |  sampleNextBatch                                                    0:00.11 ( 2.57%) 
00:00:04   298MB         |  processBucketSamples                                               0:00.11 ( 2.55%) 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | peak CPU memory used      298.84MB 
00:00:04   298MB         |  at startup               126.46MB 
00:00:04   298MB         |  AOV samples               30.81MB 
00:00:04   298MB         |  output buffers             2.63MB 
00:00:04   298MB         |  framebuffers              24.00MB 
00:00:04   298MB         |  node overhead              0.01MB 
00:00:04   298MB         |  message passing            0.05MB 
00:00:04   298MB         |  memory pools              43.10MB 
00:00:04   298MB         |  geometry                   0.00MB 
00:00:04   298MB         |   polymesh                  0.00MB 
00:00:04   298MB         |  accel structs              0.01MB 
00:00:04   298MB         |  mesh importance map        0.00MB 
00:00:04   298MB         |  strings                   24.50MB 
00:00:04   298MB         |  profiler                   1.68MB 
00:00:04   298MB         |  unaccounted               45.58MB 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | ray counts                       ( /pixel, /sample) (% total) (avg. hits) (max hits)
00:00:04   298MB         |  camera                  6656400 (  26.63,    1.00) ( 10.63%) (     0.94) (       1)
00:00:04   298MB         |  shadow                 45478079 ( 181.91,    6.83) ( 72.60%) (     0.10) (       1)
00:00:04   298MB         |  diffuse_reflect        10510438 (  42.04,    1.58) ( 16.78%) (     0.77) (       1)
00:00:04   298MB         |  total                  62644917 ( 250.58,    9.41) (100.00%) (     0.30) (       1)
00:00:04   298MB         | by ray depth:              0     1     2     3
00:00:04   298MB         |  total                   74.1% 14.8%  7.3%  3.7% 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | shader calls                     (  /pixel,  /sample) (% total)
00:00:04   298MB         |  primary                14349282 (   57.40,     2.16) (100.00%)
00:00:04   298MB         |  total                  14349282 (   57.40,     2.16) (100.00%)
00:00:04   298MB         | by ray depth:              0     1     2     3
00:00:04   298MB         |  total                   43.5% 31.4% 16.5%  8.6% 
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | geometry                         (% hit ) (instances) (  init mem,  final mem)
00:00:04   298MB         |  lists                         1 (100.0%) (        0) (      0.00,       0.00)
00:00:04   298MB         |  polymeshes                    4 (100.0%) (        0) (      0.00,       0.00)
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | geometric elements               (      min) (       avg.) (      max)
00:00:04   298MB         |  polygons                     18 (        1) (        4.5) (        6)
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | triangle tessellation            (      min) (       avg.) (      max) (/ element) (% total)
00:00:04   298MB         |  polymeshes                   36 (        2) (        9.0) (       12) (     2.00) (100.00%)
00:00:04   298MB         |  unique triangles             36 
00:00:04   298MB         |  CPU memory use             0.00MB 
00:00:04   298MB         |   vertices                  0.00MB 
00:00:04   298MB         |   vertex indices            0.00MB 
00:00:04   298MB         |   uniform indices           0.00MB 
00:00:04   298MB         |  largest polymeshes by triangle count 
00:00:04   298MB         |         12 tris -- MEsmall_box
00:00:04   298MB         |         12 tris -- MElarge_box
00:00:04   298MB         |         10 tris -- MEcornell_box
00:00:04   298MB         |          2 tris -- MELight
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   298MB         | acceleration structures:         (% total)
00:00:04   298MB         |  list                          1 ( 20.00%)
00:00:04   298MB         |  bvh                           4 ( 80.00%)
00:00:04   298MB         |  total                         5 (100.00%)
00:00:04   298MB         | -----------------------------------------------------------------------------------
00:00:04   299MB         |  
00:00:04   299MB         | releasing resources
00:00:04   228MB         |   
00:00:04   228MB         |  releasing resources
00:00:04   228MB         |   unloading 3 plugins
00:00:04   228MB         |    closing cryptomatte.so ...
00:00:04   228MB         |    closing alembic_proc.so ...
00:00:04   227MB         |    closing usd_proc.so ...
00:00:04   227MB         |   unloading plugins done
00:00:04   227MB         |  Arnold shutdown
/usr/local/Arnold/bin/noice -i arnold.exr -o noice.exr
noice 7.2.4.1 [1fee86c4] - the Arnold denoiser
Using 28 threads.
Loading images...
Loading file "arnold.exr".
Using feature AOV 'diffuse_albedo' with filter 'gaussian_filter'
Using feature AOV 'N' with filter 'gaussian_filter'
Using feature AOV 'Z' with filter 'gaussian_filter'
Working with 1 frame at 500x500
Will denoise AOV "RGBA", using associated variance
   Output file will be "noice.exr"
Start denoising (patch radius 3, search radius 9, variance 0.5)
Denoising RGBA
Finished denoising
Saving image noice.exr (500 x 500 x 4)

PBRT v4

For pbrt-v4 we need a compiled version which supports using the GPU:

$ /media/datadisk3/git/github/pbrt-v4/build/pbrt --help |& grep gpu
  --gpu                         Use the GPU for rendering. (Default: disabled)
  --gpu-device <index>          Use specified GPU for rendering.
$ /media/datadisk3/git/github/pbrt-v4/build/imgtool --help |& grep denoise-optix
denoise-optix: Denoises the image using NVIDIA's OptiX denoiser which is

$ /media/datadisk3/git/github/pbrt-v4/build/pbrt --stats --spp 64 cornell_box_v4.pbrt
pbrt version 4 (built Nov 11 2023 at 17:42:45)
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: [++++++++++++++++++++++++++++++++++++++++]  (4.1s)
Statistics:
  BVH
    Interior nodes                                                     29
    Leaf nodes                                                         30
    Nodes visited                                               960612938
    Primitives per leaf node                            36 /           30 (1.20x)
  Geometry
    Buffer cache hits                                    5 /           14 (35.71%)
    Triangles per mesh                                  38 /            7 (5.43x)
  Integrator
    Camera rays traced                                           16000000
    Path length                                                     1.852 avg [range 0 - 6]
    Regularized BSDFs                                    0 /     29626740 (0.00%)
    Zero-radiance paths                           11192144 /     29470842 (37.98%)
  Intersections
    Regular ray intersection tests                               35417428
    Shadow ray intersection tests                                20590679
    Ray-Triangle intersection tests               35192020 /    106903889 (0.33x)
  Memory
    BVH                                                              2.17 kB
    Film pixels                                                     45.78 MiB
    Light BVH                                                        0.14 kB
    Primitives                                                       0.62 kB
    Redundant vertex and index buffers                               0.26 kB
    Tokenizer buffers                                                4.78 kB
    Triangles                                                        0.73 kB
    Unreported / unused                                             20.27 MiB
  Scene
    AreaLights                                                          2
    Lights                                                              2
    Materials                                                           6
$ /media/datadisk3/git/github/pbrt-v4/build/imgtool denoise-optix noisy.exr --outfile pbrt-v4.exr

Take only 64 samples per pixel (--spp 64) and use the imgtool to denoise via OptiX.

Original vs. denoised version rendered by pbrt-v4

All the files (except the Blender scene mentioned above) you can find on my wahn-rnd-org sourcehut repository. I also remodelled the Cornell Box for the latest Blender version (3.6.5) to compare the old Cycles vs. the newest Cycles version, but that will be done in another blog post.

Blender 3.6.5 ready for more tests

Back to top