As I want to reproduce an existing photograph as closely as possible, it is essential to model a physically based camera model with depth of field. Instead of the field of view parameter that is usually used in renderers, I use more natural camera parameters focal length, f-number and sensor size to easily relate the virtual camera to their real world equivalents.
While my implementation doesn't support any more advanced camera or lens effects, it proves to be a good approximation.
See below for a comparison of increasing aperture sizes between f/32 and f/5.6. All images use a sensor size of 28.84mm and a focal length of 32mm.
Code:
src/cameras/physical.cpp
To model complex materials, it is essential to implement textures into a renderer. The most obvious application for this is a varying albedo for diffuse BSDFs but most other BSDFs can also use textures to have spatially varying parameters.
There is support for basis bitmap textures (using .exr file format), as well as very basic procedural textures for testing: A checkerboard texture and a UV texture presented in PBRTv2.
See below for renderings of the three texture types.
Code:
include/nori/texture.h
src/textures/bitmap.cpp
src/textures/checkerboard.cpp
src/textures/constant.cpp
src/textures/uv.cpp
Bump maps are a simple way to add additional detail to surfaces without changing the actual geometry. It is implemented as its own BSDF type which perturbes the local coordinate frame at the ray intersection before calling a nested child BSDF. This is useful to use different bump maps for the same 3D mesh, e.g. together with the Selection BSDF described in "Other Features". This provides maximal flexibility when designing complex objects composed out of different materials.
Like most other renderers, my implementation ignores derivatives of the normals like discussed in PBRTv2.
See below for renderings with and without bump mapping.
Code:
src/bsdfs/bumpmap.cpp
Smooth conductors work very similar to the already implemented Mirror BSDF. Additionally, their colour is tinted according to their complex index of refraction and the Fresnel equations.
Unfortunately, most online references, as well as PBRTv2, only provide these values in form of tables of measured spectral data that is acquired from real world materials. (See here for examples.) I adapted the code used in PBRTv2 that handles spectral rendering to convert such tables into simple RGB values that my renderer can use.
See below for images of a gold and copper material in comparison to reference images produced by the Mitsuba renderer.
Code:
src/bsdfs/conductor.cpp
include/nori/spectrum.h
src/spectrum.cpp
src/spectrumconverter.cpp
This is a rough version of the Smooth Conductor BSDF from above based on Microfacet Models for Refraction through Rough Surfaces by Walter et al.
I implemented only the version with the Beckmann distribution.
See below for renderings of a gold material with increasing roughness parameter. Like above, the images are compared to Mitsuba references.
There is also a visualization of the BSDF values in the warptest tool together with the results from a chi^2 test to show, that the BSDF is correctly sampled according to its probability density function.
Code:
src/bsdfs/roughconductor.cpp