## Installation Instructions in PBRT-4

1. Copy or link `sz.h`, `sz.cpp`, `nile.h`, `nile.cpp` to the `pbrt` folder,
   and add the four files to the CMakeLists.txt next to "samplers.{h,cpp}"

2. Include `sz.h` and `nile.h` in `pbrt/samplers.h`:

```cpp
#include <pbrt/sz.h>
#include <pbrt/nile.h>
```

3. In `pbrt/samplers.cpp`, function `Sampler Sampler::Create`,
   insert the appropriate `else-if` clauses:

```cpp
    else if (name == "szz" || name == "szzhash")
        sampler = SZZSamplerZHash::Create(parameters, fullRes, loc, alloc);
    else if (name == "szqart")
        sampler = SZZSamplerQARTOwen::Create(parameters, fullRes, loc, alloc);
    else if (name == "szmorton")
        sampler = SZZSamplerMorton::Create(parameters, fullRes, loc, alloc);
    else if (name == "nile" || name == "nileO2" || name == "nile13")
        sampler = NileO2Sampler::Create(parameters, fullRes, loc, alloc);
    else if (name == "start")
        sampler = StARTSampler::Create(parameters, fullRes, loc, alloc);
    else if (name == "jg")
        sampler = JGSampler::Create(parameters, fullRes, loc, alloc);
    else if (name == "artbn")
        sampler = ARTBNSampler::Create(parameters, fullRes, loc, alloc);
```

4. Add sampler declarations to `pbrt/base/sampler.h`:

```cpp
// -----------------------------------------------------------------------------
// SZZ samplers
// -----------------------------------------------------------------------------
template <class Base4Owen> class SZZSampler;
class Base4OwenIdentity;
class QARTOwen;
class ZHash;
// Concrete aliases (real types) for TaggedPointer
using SZZSamplerMorton   = SZZSampler<Base4OwenIdentity>;
using SZZSamplerQARTOwen = SZZSampler<QARTOwen>;
using SZZSamplerZHash    = SZZSampler<ZHash>;

// -----------------------------------------------------------------------------
// Nile samplers
// -----------------------------------------------------------------------------
template <class Element> class NileSampler;
// --- Elements ----------------------------------------------------------------
class ElementO2;
class ElementStART;
class ElementJG;
class ElementARTBN;
// --- Concrete aliases (real types) for TaggedPointer -------------------------
using NileO2Sampler = NileSampler<ElementO2>;
using StARTSampler = NileSampler<ElementStART>;
using JGSampler = NileSampler<ElementJG>;
using ARTBNSampler = NileSampler<ElementARTBN>;
```

Then add them to the `TaggedPointer` list in the `Sampler` class definition:
```cpp
// Sampler Definition
class Sampler
    : public TaggedPointer<  // Sampler Types
          PMJ02BNSampler, IndependentSampler, StratifiedSampler, HaltonSampler,
          PaddedSobolSampler, SobolSampler, ZSobolSampler, MLTSampler, DebugMLTSampler
          , SZZSamplerMorton
          , SZZSamplerQARTOwen
          , SZZSamplerZHash
          , NileO2Sampler
          , StARTSampler
          , JGSampler
          , ARTBNSampler
```

5. Replace file "samples.cpp" in the "Wavefront" folder, or manually edit it.

6. *(Optional)* For generating error plots, we recommend using 32-bit `.exr` images, which can be set in the film parameters of the input file.
   To avoid mistakes, you may want to set it by default. To do so, open `pbrt/film.cpp`, locate all lines reading:

   ```cpp
   bool writeFP16 = parameters.GetOneBool("savefp16", true);
   ```

   and replace `true` by `false`.
