单纯形噪声范围太小
Simplex noise range too small
我正在使用以下单纯形噪声的实现(附录 B):
https://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf
这是 Ken Perlin 自己写的。
PDF 中的代码是用 JAVA 编写的,但我已将其翻译成 C++。这是我的代码(您也可以在 C++ Shell 上 运行):
#include <iostream>
#include <string>
#include <cmath>
int i,j,k, A[3] = {0,0,0};
float u,v,w;
int T[8] = {0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a};
int b(int N, int B) { return N>>B & 1; }
int b(int i, int j, int k, int B) { return T[b(i,B)<<2 | b(j,B)<<1 | b(k,B)]; }
int shuffle(int i, int j, int k) {
return b(i,j,k,0) + b(j,k,i,1) + b(k,i,j,2) + b(i,j,k,3) +
b(j,k,i,4) + b(k,i,j,5) + b(i,j,k,6) + b(j,k,i,7) ;
}
float K(int a) {
float s = (A[0]+A[1]+A[2])/6.;
float x = u-A[0]+s, y = v-A[1]+s, z = w-A[2]+s, t = .6-x*x-y*y-z*z;
int h = shuffle(i+A[0],j+A[1],k+A[2]);
A[a]++;
if (t < 0)
return 0;
int b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
float p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
t *= t;
return 8 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
}
float noise(float x, float y, float z) {
float s = (x+y+z)/3;
i=(int)floorf(x+s); j=(int)floorf(y+s); k=(int)floorf(z+s);
s = (i+j+k)/6.; u = x-i+s; v = y-j+s; w = z-k+s;
A[0]=A[1]=A[2]=0;
int hi = u>=w ? u>=v ? 0 : 1 : v>=w ? 1 : 2;
int lo = u< w ? u< v ? 0 : 1 : v< w ? 1 : 2;
return K(hi) + K(3-hi-lo) + K(lo) + K(0);
}
int main() {
float scale = 0.0007f;
float min = 1.0f;
float max = -1.0f;
for (int x = 0; x < 100000; x++) {
float v = noise(x * scale, 0.0f, 0.0f);
if (v > max) max = v;
if (v < min) min = v;
}
printf("min = %f\r\n", min);
printf("max = %f\r\n", max);
}
问题是,调用噪声函数只给我 -0.3 和 0.3 之间的值。
我期望得到介于 -1.0 和 1.0 之间的值。
这个特定的实现有问题吗?
Obs:我没有标准化输出,也没有计算任何额外的八度音阶。
我想出了一个解决方案,但我确定这不是正确的解决方法。
我改变了这个:
return 8 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
为此:
return 26 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
现在我得到了一个不错的输出。
我正在使用以下单纯形噪声的实现(附录 B): https://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf
这是 Ken Perlin 自己写的。
PDF 中的代码是用 JAVA 编写的,但我已将其翻译成 C++。这是我的代码(您也可以在 C++ Shell 上 运行):
#include <iostream>
#include <string>
#include <cmath>
int i,j,k, A[3] = {0,0,0};
float u,v,w;
int T[8] = {0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a};
int b(int N, int B) { return N>>B & 1; }
int b(int i, int j, int k, int B) { return T[b(i,B)<<2 | b(j,B)<<1 | b(k,B)]; }
int shuffle(int i, int j, int k) {
return b(i,j,k,0) + b(j,k,i,1) + b(k,i,j,2) + b(i,j,k,3) +
b(j,k,i,4) + b(k,i,j,5) + b(i,j,k,6) + b(j,k,i,7) ;
}
float K(int a) {
float s = (A[0]+A[1]+A[2])/6.;
float x = u-A[0]+s, y = v-A[1]+s, z = w-A[2]+s, t = .6-x*x-y*y-z*z;
int h = shuffle(i+A[0],j+A[1],k+A[2]);
A[a]++;
if (t < 0)
return 0;
int b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
float p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
t *= t;
return 8 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
}
float noise(float x, float y, float z) {
float s = (x+y+z)/3;
i=(int)floorf(x+s); j=(int)floorf(y+s); k=(int)floorf(z+s);
s = (i+j+k)/6.; u = x-i+s; v = y-j+s; w = z-k+s;
A[0]=A[1]=A[2]=0;
int hi = u>=w ? u>=v ? 0 : 1 : v>=w ? 1 : 2;
int lo = u< w ? u< v ? 0 : 1 : v< w ? 1 : 2;
return K(hi) + K(3-hi-lo) + K(lo) + K(0);
}
int main() {
float scale = 0.0007f;
float min = 1.0f;
float max = -1.0f;
for (int x = 0; x < 100000; x++) {
float v = noise(x * scale, 0.0f, 0.0f);
if (v > max) max = v;
if (v < min) min = v;
}
printf("min = %f\r\n", min);
printf("max = %f\r\n", max);
}
问题是,调用噪声函数只给我 -0.3 和 0.3 之间的值。
我期望得到介于 -1.0 和 1.0 之间的值。
这个特定的实现有问题吗?
Obs:我没有标准化输出,也没有计算任何额外的八度音阶。
我想出了一个解决方案,但我确定这不是正确的解决方法。
我改变了这个:
return 8 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
为此:
return 26 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
现在我得到了一个不错的输出。