![bb907086ab920d575685152d03345315.png](https://i-blog.csdnimg.cn/blog_migrate/de63c68b0c7921fed3abd9bbd3509c41.jpeg)
从随机数到自然界中的噪声之二-Perlin Noise
Value Noiseの应用
在从随机数到自然界中的噪声之一Value Noise,我们生成了 wood pattern,这里我们先拓展和应用一下,把它
- 拓展到输入值是 vec 3,而不是之前的vec 2
- 把它渲染到 raytracing 中作为纹理
关键的部分在于三线性插值,参见文章 → 线性插值与双/三线性插值
![d977f11274c1ddb719885d9e05f4d358.png](https://i-blog.csdnimg.cn/blog_migrate/57498731f97acd7ea3c8dd413a0f05a0.png)
代码
Perlin Noise
其实理解了 Value Noise, Perlin Noise 也就没多大问题了,在 Value Noise中,我们插值(interpolate)的是随机数(random number),在Perlin Noise中,我们只是把 随机数变成了随机向量(random normalized vector),然后利用点乘来做插值,看代码:
class perlin {
private:
static const unsigned tableSize = 256;
static const unsigned tableSizeMask = tableSize - 1;
vec3 gradients[tableSize];
unsigned pTable[tableSize * 2];
int hash(const int &x, const int &y, const int &z) const{
return pTable[pTable[pTable[x]+y]+z];
}
public:
perlin (){
unsigned seed = 2016;
std::mt19937 gen(seed);
std::uniform_real_distribution<float> distrFloat;
auto randFloat = bind(distrFloat, gen);
for (unsigned i = 0; i < tableSize; i++) {
gradients[i] = unit_vector(vec3(2*randFloat()-1,2*randFloat()-1,2*randFloat()-1));
pTable[i] = i;
}
// shuffle
std::uniform_int_distribution<int> distUInt;
auto randUInt = bind(distUInt, gen);
for (size_t k = 0; k < tableSize; k++) {
unsigned i = randUInt() & tableSizeMask;
std::swap(pTable[k], pTable[i]);
pTable[k+tableSizeMask] = pTable[k];
}
}
// float floor ( float arg );
float eval(vec3 p) const {
int xi0 = ((int)std::floor(p.x())) & tableSizeMask;
int yi0 = ((int)std::floor(p.y())) & tableSizeMask;
int zi0 = ((int)std::floor(p.z())) & tableSizeMask;
int xi1 = (xi0 + 1) & tableSizeMask;
int yi1 = (yi0 + 1) & tableSizeMask;
int zi1 = (zi0 + 1) & tableSizeMask;
float tx = p.x() - ((int)std::floor(p.x()));
float ty = p.y() - ((int)std::floor(p.y()));
float tz = p.z() - ((int)std::floor(p.z()));
float u = smoothstep(tx);
float v = smoothstep(ty);
float w = smoothstep(tz);
const v