我的柏林噪音看起来很不对劲,几乎像灰色T恤材料(石南花)。为什么?

问题描述 投票:2回答:2

我尝试了代码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

c++ random perlin-noise ppm noise-generator
2个回答
2
投票

要将范围为[-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;

0
投票

这是您的代码的直接副本吗?您为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}

获得良好的灰度图像。

© www.soinside.com 2019 - 2024. All rights reserved.