Images as Textures
Relevant code:
src/textures/imagetexture.cpp
Implementation Details:
For this feature, an input texture image is loaded, then the texture of
the object is decided by the input texture image. We write a class inheriting
the Texture class, and the member function eval()
would return the corresponding rgb value of input u v coordinate.
To make the texture looks more smooth, we use bilinear interpolation on the quired
position. Also, to make it more flexiable, parameter scale can be added
to adjust the texture's scale.
Validation:
The texture image we used for testing:

Bump Mapping
Relevant code:
src/bsdfs/bumpmap.cppsrc/geometry/mesh.cppsrc/geometry/sphere.cpp
Implementation Details:
For this feature, an input image is loaded as the bumpmap. We implement a bumpmap class inheriting
from the BSDF class, which contains a actual BSDF and a image texture. When we need the BSDF
information of the intersection point, first we adjust the frame of that point according to the input image
texture, after that, the adjusted intersection would be passed to the actual BSDF and get the results. A member
variable enhance is also added to adjust the strength of the bumpmap.
Validation:
The bumpmap image we used for testing:

Simple Extra BSDF: Conductor
Relevant code:
src/bsdfs/conductor.cpp
Implementation Details:
We implement a ConductorBSDF class inheriting
from the BSDF class, which contains three member variables:
eta, k and specular_reflectance.
Since it is a discrete BSDF, the eval() and pdf()
function of it would directly return 0. For sample(), we use
the conductor fresnel function by K.D. Moeller.
Validation:
We compare our result with the result from Mitsuba 3.
Simple Extra BSDF: Blend BSDF
Relevant code:
src/bsdfs/blendbsdf.cpp
Implementation Details:
This feature intends to combine two different BSDF with a given weight factor. To
achive this goal, we implement a BlendBSDF class inheriting
from the BSDF class. This BlendBSDF requires to BSDF as input,
a float weight factor weight is also needed to balance this two BSDF. For
eval() and pdf() function, we call the two member BSDF and weight
their result by the weight. For function sample(), we use a random variable to
decide use which BSDF, and call the corresponding sample().
Validation:
Use BlendBSDF to combine Diffuse and Dielectric with
different weight (0.00, 0.25, 0.50, 0.75, 1.00 from left to right). The result is shown below:

Use BlendBSDF to combine Diffuse and Conductor with
different weight (0.00, 0.25, 0.50, 0.75, 1.00 from left to right). The result is shown below:

BlendBSDF to combine Dielectric and Conductor with
different weight (0.00, 0.25, 0.50, 0.75, 1.00 from left to right). The result is shown below:

Stratified Sampling
Relevant code:
src/sample/stratified.cppsrc/core/render.cpp
Implementation Details:
For this feature, we implement a StratifiedSampler class inheriting
from the Sampler class. Besides the sampleCount parameter,
an additional dimension parameter is also added. Every sample would generate
the predefined dimension, and each sample would distributed relatively evenly across the
sample space. If the sample use more than the predefined dimension, it will sample value randomly.
Validation:
Here we compare the rendering result with stratified sampling and independent sampling. It can be seen clearly that the noise distribution of the one with stratified sampling is more even than the one with independent sampling.
Environment Map Emitter
Relevant code:
src/emitters/envmap.cppinclude/kombu/envmap.hsrc/integrators/path_mats.cppsrc/integrators/path_mis.cpp
Implementation Details:
This feature intends to provide a background environment light to the rendered scene. It would load an image as the environment map as an emitter and wrap the image to a infinite large sphere. The return value of the emitter only depends on the angle of the sampled ray. In practice, we also need to give a shadow ray, whose length depends on the bounding sphere of the scene to enable the light sampling. Also, importance sample is done by calculating the pdf and cdf of the image. Bilinear interpolation is applied to make it looks more smooth. The implementation is based on this paper: https://web.cs.wpi.edu/~emmanuel/courses/cs563/S07/projects/envsample.pdf
Validation:
Here we compare our result with mitsuba 3. There are a diffuse sphere and a dielectric sphere in the scene to check the correcness.
This is the environment map for testing.

Disney BSDF (metallic, roughness, specular, sheen, sheen_tint)
Relevant code:
src/bsdf/disney_principled.cppinclude/kombu/disney_utils.hinclude/kombu/principledhelpers.h
Implementation Details:
We implement 5 parameters of Disney Principled BSDF, which are roughness, specular, metallic, sheen and sheen_tint.
This feature makes it possible to adjust the material of surface of certain object more flexiable to
be adjusted. Basically, Disney BSDF is a mix of different material. metallic describes how much
is the metal contributes to the material (0 is dielectric and 1 is metal). roughness
controls the roughness of the surface by weighting diffuse and specular reflections.
specular decribes the amount of incident specular reflection. Used to replace the rate of refraction.
sheen is an additional grazing component, mainly for cloth, and sheen_tint controls
the color of sheen.
Our implementation uses this tutorial from UCSD
and Mitsuba 3 as references.
Validation:
Let metallic be (0.00, 0.25, 0.50, 0.75, 1.00 from left to right), fix other parameters:

Let roughness be (0.00, 0.25, 0.50, 0.75, 1.00 from left to right), fix other parameters:

Let sheen be (0.00, 0.25, 0.50, 0.75, 1.00 from left to right), fix other parameters:

Let sheen_tint be (0.00, 0.25, 0.50, 0.75, 1.00 from left to right), fix other parameters:

Let specular be (0.00, 0.25, 0.50, 0.75, 1.00 from left to right), fix other parameters:

Compare metallic = 0 and metallic = 1:
Compare roughness = 0 and roughness = 1:
Compare sheen = 0 and sheen = 1:
Compare sheen_tint = 0 and sheen_tint = 1:
Compare specular = 0 and specular = 1: