我尝试了代码here的快速而肮脏的翻译。
但是,我的版本输出的噪音可与灰色T恤材质相媲美,如果它让你满意,可以选择石南花:
#include <fstream>
#include "perlin.h"
double Perlin::cos_Interp(double a, double b, double x)
{
ft = x * 3.1415927;
f = (1 - cos(ft)) * .5;
return a * (1 - f) + b * f;
}
double Perlin::noise_2D(double x, double y)
{
/*
int n = (int)x + (int)y * 57;
n = (n << 13) ^ n;
int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
return 1.0 - ((double)nn / 1073741824.0);
*/
int n = (int)x + (int)y * 57;
n = (n<<13) ^ n;
return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
double Perlin::smooth_2D(double x, double y)
{
corners = ( noise_2D(x - 1, y - 1) + noise_2D(x + 1, y - 1) + noise_2D(x - 1, y + 1) + noise_2D(x + 1, y + 1) ) / 16;
sides = ( noise_2D(x - 1, y) + noise_2D(x + 1, y) + noise_2D(x, y - 1) + noise_2D(x, y + 1) ) / 8;
center = noise_2D(x, y) / 4;
return corners + sides + center;
}
double Perlin::interp(double x, double y)
{
int x_i = int(x);
double x_left = x - x_i;
int y_i = int(y);
double y_left = y - y_i;
double v1 = smooth_2D(x_i, y_i);
double v2 = smooth_2D(x_i + 1, y_i);
double v3 = smooth_2D(x_i, y_i + 1);
double v4 = smooth_2D(x_i + 1, y_i + 1);
double i1 = cos_Interp(v1, v2, x_left);
double i2 = cos_Interp(v3, v4, x_left);
return cos_Interp(i1, i2, y_left);
}
double Perlin::perlin_2D(double x, double y)
{
double total = 0;
double p = .25;
int n = 1;
for(int i = 0; i < n; ++i)
{
double freq = pow(2, i);
double amp = pow(p, i);
total = total + interp(x * freq, y * freq) * amp;
}
return total;
}
int main()
{
Perlin perl;
ofstream ofs("./noise2D.ppm", ios_base::binary);
ofs << "P6\n" << 512 << " " << 512 << "\n255\n";
for(int i = 0; i < 512; ++i)
{
for(int j = 0; j < 512; ++j)
{
double n = perl.perlin_2D(i, j);
n = floor((n + 1.0) / 2.0 * 255);
unsigned char c = n;
ofs << c << c << c;
}
}
ofs.close();
return 0;
}
除了添加ppm图像生成代码之外,我不相信我偏离了上述网站的方向,但我再次承认不能完全掌握代码中发生的事情。
正如您在评论部分所看到的,我尝试了两种(类似的)方法来生成噪声的伪随机数。我还尝试了将perlin_2D返回的数字缩放到RGB颜色值的不同方法。这两种编辑代码的方式刚刚产生了不同的T恤材质。所以,我不得不相信,我无法识别出更大的事情。
另外,我正在使用g ++和c ++ 11标准进行编译。
编辑:这是一个例子:http://imgur.com/Sh17QjK
要将范围为[-1.0,1.0]的double
转换为[0,255]范围内的整数:
n = floor((n + 1.0) / 2.0 * 255.99);
要将其作为二进制值写入PPM文件:
ofstream ofs("./noise2D.ppm", ios_base::binary);
...
unsigned char c = n;
ofs << c << c << c;
这是您的代码的直接副本吗?您为Y分数值分配了一个整数 - 它是一个拼写错误,如果您不修复它会抛出整个噪声算法:
double Perlin::interp(double x, double y)
{
int x_i = int(x);
double x_left = x - x_i;
int y_i = int(y);
double y_left = y = y_i; //This Should have a minus, not an "=" like the line above
.....
}
我的猜测是,如果您使用正确的颜色计算成功生成位图,那么您会得到垂直条纹或沿着这些线条的东西?
您还需要记住,Perlin生成器通常会在-1到1的范围内吐出数字,您需要将结果值相乘:
值* 127 + 128 = {R,G,B}
获得良好的灰度图像。