Procedural Textures (5 pts)
Implementation
Added files:
proceduraltexture.cpp
proceduraltexture3d.cpp
texture3d.h
diffuse3d.cpp
perlin.h
perlin.cpp
As a noise function for procedural texture, I have chosen Perlin noise and based my implementation on PBRTv3 10.6.1.
The implemented noise
function maps arbitrary points in $\mathbb{R}^3$ to $[-1, 1]$.
Note that one can actually formulate a tighter range for Perlin noise (e.g. see here),
but for simplicity, I made the common assumption of keeping the range at $[-1, 1]$.
However, to compensate for the fact that over-approximating the range leads to missing values close to the borders when mapping e.g. to $[0, 1]$
for getting a color, I have added a rangeScale
parameter (used only for fBm), which allows me to apply custom scaling to the value range.
Values that subsequently are out of the desired range will simply get clamped.
To create more interesting textures with finer variations at different scales, I have further implemented fractional Brownian motion (fBm),
which is created by summing multiple layers of Perlin noise. For every higher layer, we increase the frequency and decrease the amplitude
of our Perlin noise through a geometric progression.
The user can control how quickly the frequency increases through the lacunarity
parameter, how quickly the amplitude decreases
through the gain
parameter, and how many layers are computed with the nrOctaves
parameter.
My implementation follows PBRTv3 10.6.3, with the difference of disregarding anti-aliasing.
fBm can be used as a texture itself already, but also as a building block for many procedural textures. I have chosen to use it for creating a procedural marble texture, following the approach described in PBRTv3 10.6.6.
As all of these three textures (Perlin, fBm and marble) are implemented in the same texture, the user can simply set the type
parameter
to choose between textures.
Further configurable parameters are scale
and offset
, which are simply implemented through first adding the offset vector to the uv
coordinates and afterwards multiplying them (component-wise) with the scale vector.
I have already implemented 3D Perlin noise, which can easily be used also for 2D noise by simply keeping one of the input coordinates constant. This allows avoiding distortions when applying the procedural textures to an arbitrary 3D object, by using the actual point in space directly as input. However, this also requires an integrator which is able to handle this and a new texture type, since by default only a 2D vector is expected as input for uv in Nori.
Validation
As a 1:1 comparison with other procedural textures is not really possible, I will display some example renders of my procedural textures with varying parameters in the following.
Perin noise at different scales

scale = [1,1]

scale = [10,10]

scale = [1,10]
Fractional brownian motion with varying parameters (3D Texture), rangeScale
set to 0.5

lacunarity = 2.0, gain = 0.5

lacunarity = 1.5, gain = 0.5

lacunarity = 2.0, gain = 0.8
Marble texture (2D Texture)

lacunarity=2.2, gain=0.5, marbleVariation_left = 0.0, marbleVariation_right = 0.8
Effect of marbleVariation
parameter

marbleVariation = 0.6

marbleVariation = 1.2