SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLPathtracer.h
Go to the documentation of this file.
1 /**
2  * \file SLPathtracer.h
3  * \date February 2014
4  * \authors Thomas Schneiter, Marcus Hudritsch
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #ifndef SLPATHTRACER_H
11 #define SLPATHTRACER_H
12 
13 #include <SLRaytracer.h>
14 
15 //-----------------------------------------------------------------------------
16 //! Classic Monte Carlo Pathtracing algorithm for real global illumination
17 class SLPathtracer : public SLRaytracer
18 {
19 public:
20  SLPathtracer();
21  ~SLPathtracer() { SL_LOG("Destructor : ~SLPathtracer"); }
22 
23  // classic ray tracer functions
25  void renderSlices(bool isMainThread,
26  SLint currentSample,
27  SLuint threadNum);
28  //! Traces one ray. bsdfPdf is the solid angle density with which the
29  /*! scattering at the previous vertex produced this ray, or the negative
30  sentinel PDF_NO_MIS if next event estimation cannot generate the same
31  path (the primary ray, and every specular or transmissive bounce). It is
32  what lets a light hit be weighted against the light sampling in shade(). */
33  SLCol4f trace(SLRay* ray, SLfloat bsdfPdf);
34  SLCol4f shade(SLRay* ray, SLCol4f* mat);
35  void saveImage();
36  void computeNoise();
37 
38  // Setters
39  void calcDirect(SLbool di) { _calcDirect = di; }
40  void calcIndirect(SLbool ii) { _calcIndirect = ii; }
41  void sampleClamp(SLfloat max) { _sampleClamp = max; }
42 
43  // Getters
44  SLbool calcDirect() const { return _calcDirect; }
45  SLbool calcIndirect() const { return _calcIndirect; }
46  SLfloat sampleClamp() const { return _sampleClamp; }
47 
48  //! Mean relative standard error of the pixels of the last render
49  /*! How far the average pixel is expected to sit from the value this
50  estimator converges to, as a fraction of the pixel itself. It is a measure
51  of the noise only: it says nothing about the bias that sampleClamp adds,
52  and it falls monotonically as the clamp tightens. See computeNoise. */
53  SLfloat noiseRSE() const { return _noiseRSE; }
54 
55  //! Relative standard error of the noisiest 0.1% of the pixels
56  /*! The figure to watch for fireflies. A firefly covers a handful of pixels
57  out of hundreds of thousands, so it barely moves noiseRSE, but it dominates
58  this one.
59 
60  It has a floor that comes straight from its definition: it reports the pixel
61  at rank 99.9%, so it only moves once the fireflies reach more than 0.1% of
62  the image. Measured on synthetic fireflies at 640x360 and 1000 spp, with the
63  outliers 3000 times an ordinary sample:
64 
65  firefly pixels noiseRSE noiseRSE999
66  0.010% 0.00320 0.00338
67  0.100% 0.00370 0.00342 still an ordinary pixel
68  0.200% 0.00421 0.60547
69  5.000% 0.02910 0.75061
70 
71  Below that threshold this figure reads as if the image were clean and only
72  noiseRSE moves, by very little. It is the right figure for the Muttenzer
73  Box, whose fireflies cover about 4% of the far wall (see _sampleClamp), but
74  a scene with rarer ones needs a higher percentile or the maximum. */
75  SLfloat noiseRSE999() const { return _noiseRSE999; }
76 
77  //! Monte Carlo efficiency, the inverse of variance times time
78  /*! The figure to compare two renderers or two settings with, because it is
79  the only one that stays fair when a change alters what a sample costs, as
80  Russian roulette does. It does not depend on the sample count: the variance
81  of a pixel falls as 1/N while the render time grows as N, so their product
82  is constant in N and two renders at different samples per pixel can be
83  compared directly. Higher is better. */
85  {
86  return _noiseRSE > 0.0f && _renderSec > 0.0f
87  ? 1.0f / (_noiseRSE * _noiseRSE * _renderSec)
88  : 0.0f;
89  }
90 
91 private:
92  function<void(bool, int, SLuint)> renderSlicesPTAsync;
93 
94  SLbool _calcDirect; //!< flag to calculate direct illumination
95  SLbool _calcIndirect; //!< flag to calculate indirect illumination
96 
97  //! Upper limit on the radiance of a single sample, 0 to switch it off
98  /*! A firefly is a path that carries far more energy than the pixel it lands
99  in, most often a caustic: light that reaches a diffuse surface through the
100  mirror or the glass sphere. The estimator is right about it, but such a path
101  is found so seldom that the average is still visibly lumpy after a thousand
102  samples. Capping what one sample may contribute removes it at once.
103 
104  This is a deliberate bias, and the only one left in the renderer: it
105  discards the part of a caustic above the limit and makes it darker than it
106  is. Measured on the Muttenzer Box at 100 spp, against no clamp:
107 
108  limit fireflies, far wall mean radiance of the caustic
109  off 4.35% 1.000
110  30 4.75% 0.985
111  10 4.08% 0.938
112  3 0.02% 0.695
113 
114  The fireflies of this scene sit between 3 and 10, so 30 does nothing and 10
115  barely helps. 3 removes them almost entirely and costs 2 to 5% on ordinary
116  surfaces, 15% on the ceiling below the light and 30% on the caustic under
117  the glass sphere. That is the trade, and it is why this is a menu item that
118  can be switched off rather than a constant.
119 
120  Note that it caps the SAMPLE and never the running mean. Clamping the mean
121  is the defect that the float accumulation buffer removed: it froze the
122  fireflies at a wrong value instead of averaging them away. */
124 
125  //! Linear, unclamped sum of all radiance samples taken so far per pixel
126  /*! The progressive mean of a path tracer must never be kept in an 8 bit
127  image. Rounding the running mean to 1/255 after every sample stops the
128  convergence as soon as the correction of one sample, which is
129  |sample - mean| / sampleNo, falls below half a quantisation step, i.e. as
130  soon as sampleNo > 510 * |sample - mean|. A bright outlier (a firefly) then
131  freezes at a wrong value and never averages out again, no matter how many
132  samples are rendered. That is why this buffer holds the raw sum in full
133  float precision and is divided by the sample number for the display only.
134  Its size is _images[0]->width() * _images[0]->height() and it is indexed
135  with y * width + x. */
136  vector<SLCol4f> _radianceSum;
137 
138  //! Sum and sum of squares of the luminance of every sample, per pixel
139  /*! The two moments that the variance of a pixel is computed from, in
140  computeNoise. Luminance rather than colour, because the noise of a pixel is
141  one number and not three, and it is linear, so summing the luminance of the
142  samples and taking the luminance of _radianceSum come to the same thing.
143 
144  They are double and not float, although _radianceSum is float, because the
145  variance is the small difference of two large sums, S2 - S1*S1/N. In a quiet
146  region those two agree to several digits and a float would leave almost none
147  of the result. A firefly makes it worse from the other side: 1e4 squared is
148  1e8, and adding an ordinary 1e-4 to that is lost entirely in float. Double
149  carries both ends. The cost is 16 bytes per pixel, 3.7 MB at 640x480.
150 
151  Indexed like _radianceSum, with y * width + x. */
152  vector<SLdouble> _lumSum;
153  vector<SLdouble> _lumSumSq;
154 
155  SLfloat _noiseRSE; //!< mean relative standard error, see noiseRSE()
156  SLfloat _noiseRSE999; //!< the same for the worst 0.1%, see noiseRSE999()
157 };
158 //-----------------------------------------------------------------------------
159 #endif
float SLfloat
analog to GLfloat
Definition: SL.h:200
#define SL_LOG(...)
Some debugging and error handling macros.
Definition: SL.h:279
unsigned int SLuint
analog to GLuint
Definition: SL.h:198
bool SLbool
analog to GLbool
Definition: SL.h:202
int SLint
analog to GLint
Definition: SL.h:197
typedef void(SL_STDCALL *cbOnImGuiBuild)(SLScene *s
Callback function typedef for ImGui build function.
Classic Monte Carlo Pathtracing algorithm for real global illumination.
Definition: SLPathtracer.h:18
SLbool _calcIndirect
flag to calculate indirect illumination
Definition: SLPathtracer.h:95
SLCol4f shade(SLRay *ray, SLCol4f *mat)
SLbool render(SLSceneView *sv)
SLfloat noiseRSE() const
Mean relative standard error of the pixels of the last render.
Definition: SLPathtracer.h:53
void calcDirect(SLbool di)
Definition: SLPathtracer.h:39
SLbool calcIndirect() const
Definition: SLPathtracer.h:45
void computeNoise()
vector< SLdouble > _lumSumSq
Definition: SLPathtracer.h:153
SLbool _calcDirect
flag to calculate direct illumination
Definition: SLPathtracer.h:94
vector< SLCol4f > _radianceSum
Linear, unclamped sum of all radiance samples taken so far per pixel.
Definition: SLPathtracer.h:136
void sampleClamp(SLfloat max)
Definition: SLPathtracer.h:41
SLfloat _noiseRSE
mean relative standard error, see noiseRSE()
Definition: SLPathtracer.h:155
void renderSlices(bool isMainThread, SLint currentSample, SLuint threadNum)
void calcIndirect(SLbool ii)
Definition: SLPathtracer.h:40
SLfloat sampleClamp() const
Definition: SLPathtracer.h:46
SLfloat efficiency() const
Monte Carlo efficiency, the inverse of variance times time.
Definition: SLPathtracer.h:84
void saveImage()
Saves the current PT image as PNG image.
SLbool calcDirect() const
Definition: SLPathtracer.h:44
SLfloat _sampleClamp
Upper limit on the radiance of a single sample, 0 to switch it off.
Definition: SLPathtracer.h:123
function< void(bool, int, SLuint)> renderSlicesPTAsync
Definition: SLPathtracer.h:92
SLfloat _noiseRSE999
the same for the worst 0.1%, see noiseRSE999()
Definition: SLPathtracer.h:156
SLCol4f trace(SLRay *ray, SLfloat bsdfPdf)
Traces one ray. bsdfPdf is the solid angle density with which the.
SLfloat noiseRSE999() const
Relative standard error of the noisiest 0.1% of the pixels.
Definition: SLPathtracer.h:75
vector< SLdouble > _lumSum
Sum and sum of squares of the luminance of every sample, per pixel.
Definition: SLPathtracer.h:152
Ray class with ray and intersection properties.
Definition: SLRay.h:40
SLRaytracer hold all the methods for Whitted style Ray Tracing.
Definition: SLRaytracer.h:58
SLfloat _renderSec
Rendering time in seconds.
Definition: SLRaytracer.h:153
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69