간단한 소음 발생


27

다음과 같은 노이즈를 생성하려고합니다.

여기에 이미지 설명을 입력하십시오여기에 이미지 설명을 입력하십시오

( Perlin Noise 이해대한 이미지 제공 )

나는 기본적으로 작은 "잔물결"이 많은 소음을 찾고 있습니다. 다음은 바람직하지 않습니다.

여기에 이미지 설명을 입력하십시오

간단한 것이 있습니까이를 수행 방법이 있습니까? 나는 지금 일주일 동안 perlin과 simplex를 살펴 보았고 JavaScript에서 작동하도록 할 수 없거나 그렇게 할 때 그러한 이미지를 생성하는 데 올바른 매개 변수가 없거나 매우 심각합니다 느린.

내가 게시 한 3 개의 이미지는 아마도 동일한 알고리즘이지만 다른 규모로 달성 될 수 있음을 이해하지만 해당 알고리즘은 필요하지 않습니다. 첫 번째 이미지와 같은 것을 이상적으로 달성하려면 매우 간단한 알고리즘이 필요합니다. 어쩌면 어떤 종류의 흐림 효과가 효과가 있지만 결과를 얻을 수는 없습니다.

나는 이것을 JavaScript로 개발하고 있지만 모든 종류의 코드 또는 간단하고 자세한 설명이 효과가 있습니다.


3
참고로 원하는 것은 분명히 Perlin 노이즈입니다. 언급 한 "바람직하지 않은"효과는 서로 추가 된 몇 옥타브의 Perlin 노이즈로 구성됩니다 (이를 프랙탈 노이즈라고도 함). 실제로 하나의 이미지 만 필요합니까, 아니면 시간이 지남에 따라 이미지를 바꾸시겠습니까? 그렇다면, 당신은 어떤 영향을 줍니까?
sam hocevar

@ SamHocevar 즉시 생성하고 싶습니다. 이 질문에 언급 된 내용을 재현하려고 합니다.
Xeon06

JS perlin 노이즈 구현을 발견 하여 jsFiddle에 통합했습니다 . 그러나 결과는 플래시의 펄린 노이즈 구현과는 상당히 다르므로 플래시와 함께 제공되는 펄린 노이즈 생성기의 구현 세부 정보에 대해 궁금해합니다.
bummzack

실제로 @bummzack, 그것은 플래시 생성기가 내 목적에 맞는 완벽한 소음을 생성하는 것 같습니다. 게시 한 Fiddle에 대해 적절한 임계 값을 얻을 수 없습니다.
Xeon06

나는 이것에도 관심이 있기 때문에 stackoverflow에 의문을 제기했다 . 잘만되면 우리는 거기에 약간의 대답을 얻을 것이다.
bummzack

답변:


16

기존 답변은 질문의 이미지가 보여주는 것을 달성하는 좋은 방법을 제공하지만 의견은 아래에 표시된 것처럼 이미지를 생성하는 것이 목표임을 밝혔습니다.

펄린 소음 난기류

이 유형의 노이즈는 문제의 이미지에 표시된 노이즈와 매우 다르며 격리 된 얼룩을 형성합니다.

잡음이 종류가 호출 밝혀 난류 되는 (따른 이 CPU 보석 문서 는 다음과 같이 구현된다) (단 noise-1..1의 값을 리턴하여 펄린 노이즈의 함수이다)

double turbulence(double x, double y, double z, double f) {
    double t = -.5;
    for ( ; f <= W/12 ; f *= 2) // W = Image width in pixels
        t += abs(noise(x,y,z,f) / f);
    return t;
}

위에서 설명한 난류 함수 를 사용하여이 JavaScript Perlin-noise 구현 을 매시하면 위 이미지와 비슷한 노이즈가 생성됩니다.

난기류 소음

위의 이미지를 생성하는 데 사용 된 JavaScript 코드는 이 jsFiddle 에서 찾을 수 있습니다 .


3
그것은 이상한 코드이며, JavaScript 버전은 Java 버전과 상당히 다르며 JavaScript 버전은 기본적으로 완전히 작성하는 방식입니다 return Math.abs(this.noise(x,y,z)*2)-.5.
aaaaaaaaaaaa

@aaaaaaaaaaaa Ken Perlin 자신과 함께 특정 코드 블록을 작성했습니다.
b1nary.atr0phy 19:43에

15

예시 이미지는 핑크 노이즈와 매우 비슷합니다. 다음과 같이 생성됩니다.

  • 먼저 부드러운 임의 노이즈가 있습니다. 일반적으로 이것은 정수 좌표가있는 포인트에서 의사 난수 값을 계산하고 이러한 값을 어떻게 든 보간하여 수행됩니다. 이 단계의 결과는 다음과 같습니다.

    여기에 이미지 설명을 입력하십시오

  • 다음으로, 우리는이 잡음을 가져 와서 "누르고"주파수를 증가시킵니다. 가장 간단한 공식은 n2 (x, y) = n1 (x f, y f)입니다. 이러한 방식으로, 잡음 패턴은 두 개의 다이렉트 론 모두에서 f 번 압착된다. 규칙을 해체하기 위해이 단계에서 더 나은 노이즈 알고리즘도 노이즈 패턴을 회전 및 / 또는 변환합니다.

  • 그런 다음이 압착 패턴에 1보다 작은 값을 곱한 후 첫 번째 패턴에 추가합니다. 실제로, 우리는 저주파 패턴 위에 작은 고주파 변동을 추가합니다. 결과는 다음과 같습니다.

    여기에 이미지 설명을 입력하십시오

  • 단계 2 및 3은 더 세밀하고 세밀한 내용을 추가하여 여러 번 반복 될 수 있습니다. 순 결과는 일반적으로 적십자가있는 예와 같습니다. 그러나 알고리즘에 사용할 수있는 3 개의 매개 변수가 있습니다.

    • 옥타브 수-즉, 생성 단계 수. 더 많은 단계는 결과 패턴에서 더 세밀한 세부 사항을 의미합니다.
    • 고집. 모든 단계에서 곱해지는 값입니다. 일반적으로 지속성은 0과 1 사이입니다. 높은 지속성 값은 일반적으로 세부 사항이 거의없는 "잡음없는"패턴을 생성합니다. 낮은 지속성은 미묘한 디테일로 부드러운 패턴을 만듭니다.
    • 어리 석음. 모든 단계에서 사용하는 "압착"계수입니다. Lacunarity는 영속성처럼 작동하지만 정확하게는 아닙니다. 낮은 lacunarity는 더 부드러운 패턴을 생성하고 높은 lacunarity는 더 선명하고 대비가 높은 패턴을 만듭니다.

여기 몇 가지 예가 있어요.

높은 지속성 : 높은 지속성 노이즈

높은 lacunarity : 높은 lacunarity 노이즈

낮은 lacunarity : 낮은 lacunarity 노이즈

이 파라미터를 가지고 노는 것이 유일한 것은 아닙니다. 노이즈 패턴에 문자를 추가 할 수있는 좋은 기술 중 하나는 섭동 을 사용 하는 것입니다. 즉 노이즈 함수의 입력 좌표에 노이즈를 추가하는 것입니다.

예를 들어, 주어진 좌표와 랜덤 시드에 노이즈를 생성하는 함수가 있다고 가정합니다 Noise(x,y, seed). 당신은 Noise(x+Noise(x,y,234), y+Noise(x,y,6544), seed)교란 된 가치를 얻기 위해 같은 것을 사용할 수 있습니다 . 이것은 다음과 같은 패턴으로 이어질 수 있습니다 (소음은 노이즈가 아닌 원형 패턴에 적용됩니다).

난류

자세한 내용을 보려면 libnoise (C ++) 또는 CoherentNoise (C #)를 살펴보십시오 . 불행히도, 나는 자바 스크립트 노이즈 생성 라이브러리를 모른다.


6

코드가 주석 처리됩니다. 신용은 Sean McCullough에게갑니다. http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf

// Ported from Stefan Gustavson's java implementation
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
// Read Stefan's excellent paper for details on how this code works.
//
// Sean McCullough banksean@gmail.com

/**
* You can pass in a random number generator object if you like.
* It is assumed to have a random() method.
*/
var SimplexNoise = function(r) {
if (r == undefined) r = Math;
  this.grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],
                                 [1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],
                                 [0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]];
  this.p = [];
  for (var i=0; i<256; i++) {
this.p[i] = Math.floor(r.random()*256);
  }
  // To remove the need for index wrapping, double the permutation table length
  this.perm = [];
  for(var i=0; i<512; i++) {
this.perm[i]=this.p[i & 255];
}

  // A lookup table to traverse the simplex around a given point in 4D.
  // Details can be found where this table is used, in the 4D noise method.
  this.simplex = [
    [0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0],
    [0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0],
    [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
    [1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0],
    [1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,3,1],[0,0,0,0],[2,1,3,0],
    [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
    [2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0],
    [2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]];
};

SimplexNoise.prototype.dot = function(g, x, y) {
return g[0]*x + g[1]*y;
};

SimplexNoise.prototype.noise = function(xin, yin) {
  var n0, n1, n2; // Noise contributions from the three corners
  // Skew the input space to determine which simplex cell we're in
  var F2 = 0.5*(Math.sqrt(3.0)-1.0);
  var s = (xin+yin)*F2; // Hairy factor for 2D
  var i = Math.floor(xin+s);
  var j = Math.floor(yin+s);
  var G2 = (3.0-Math.sqrt(3.0))/6.0;
  var t = (i+j)*G2;
  var X0 = i-t; // Unskew the cell origin back to (x,y) space
  var Y0 = j-t;
  var x0 = xin-X0; // The x,y distances from the cell origin
  var y0 = yin-Y0;
  // For the 2D case, the simplex shape is an equilateral triangle.
  // Determine which simplex we are in.
  var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
  if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1)
  else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
  // c = (3-sqrt(3))/6
  var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
  var y1 = y0 - j1 + G2;
  var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
  var y2 = y0 - 1.0 + 2.0 * G2;
  // Work out the hashed gradient indices of the three simplex corners
  var ii = i & 255;
  var jj = j & 255;
  var gi0 = this.perm[ii+this.perm[jj]] % 12;
  var gi1 = this.perm[ii+i1+this.perm[jj+j1]] % 12;
  var gi2 = this.perm[ii+1+this.perm[jj+1]] % 12;
  // Calculate the contribution from the three corners
  var t0 = 0.5 - x0*x0-y0*y0;
  if(t0<0) n0 = 0.0;
  else {
    t0 *= t0;
    n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient
  }
  var t1 = 0.5 - x1*x1-y1*y1;
  if(t1<0) n1 = 0.0;
  else {
    t1 *= t1;
    n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1);
  }
  var t2 = 0.5 - x2*x2-y2*y2;
  if(t2<0) n2 = 0.0;
  else {
    t2 *= t2;
    n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2);
  }
  // Add contributions from each corner to get the final noise value.
  // The result is scaled to return values in the interval [-1,1].
  return 70.0 * (n0 + n1 + n2);
};

// 3D simplex noise
SimplexNoise.prototype.noise3d = function(xin, yin, zin) {
  var n0, n1, n2, n3; // Noise contributions from the four corners
  // Skew the input space to determine which simplex cell we're in
  var F3 = 1.0/3.0;
  var s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
  var i = Math.floor(xin+s);
  var j = Math.floor(yin+s);
  var k = Math.floor(zin+s);
  var G3 = 1.0/6.0; // Very nice and simple unskew factor, too
  var t = (i+j+k)*G3;
  var X0 = i-t; // Unskew the cell origin back to (x,y,z) space
  var Y0 = j-t;
  var Z0 = k-t;
  var x0 = xin-X0; // The x,y,z distances from the cell origin
  var y0 = yin-Y0;
  var z0 = zin-Z0;
  // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
  // Determine which simplex we are in.
  var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
  var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
  if(x0>=y0) {
    if(y0>=z0)
      { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order
      else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order
      else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order
    }
  else { // x0<y0
    if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order
    else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order
    else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order
  }
  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
  // c = 1/6.
  var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
  var y1 = y0 - j1 + G3;
  var z1 = z0 - k1 + G3;
  var x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
  var y2 = y0 - j2 + 2.0*G3;
  var z2 = z0 - k2 + 2.0*G3;
  var x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
  var y3 = y0 - 1.0 + 3.0*G3;
  var z3 = z0 - 1.0 + 3.0*G3;
  // Work out the hashed gradient indices of the four simplex corners
  var ii = i & 255;
  var jj = j & 255;
  var kk = k & 255;
  var gi0 = this.perm[ii+this.perm[jj+this.perm[kk]]] % 12;
  var gi1 = this.perm[ii+i1+this.perm[jj+j1+this.perm[kk+k1]]] % 12;
  var gi2 = this.perm[ii+i2+this.perm[jj+j2+this.perm[kk+k2]]] % 12;
  var gi3 = this.perm[ii+1+this.perm[jj+1+this.perm[kk+1]]] % 12;
  // Calculate the contribution from the four corners
  var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
  if(t0<0) n0 = 0.0;
  else {
    t0 *= t0;
    n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0, z0);
  }
  var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
  if(t1<0) n1 = 0.0;
  else {
    t1 *= t1;
    n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1, z1);
  }
  var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
  if(t2<0) n2 = 0.0;
  else {
    t2 *= t2;
    n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2, z2);
  }
  var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
  if(t3<0) n3 = 0.0;
  else {
    t3 *= t3;
    n3 = t3 * t3 * this.dot(this.grad3[gi3], x3, y3, z3);
  }
  // Add contributions from each corner to get the final noise value.
  // The result is scaled to stay just inside [-1,1]
  return 32.0*(n0 + n1 + n2 + n3);
};

또한 PRNG를 사용하면 쉽게 복구 할 수있는 결과를 얻을 수 있습니다

/*
  I've wrapped Makoto Matsumoto and Takuji Nishimura's code in a namespace
  so it's better encapsulated. Now you can have multiple random number generators
  and they won't stomp all over eachother's state.

  If you want to use this as a substitute for Math.random(), use the random()
  method like so:

  var m = new MersenneTwister();
  var randomNumber = m.random();

  You can also call the other genrand_{foo}() methods on the instance.

  If you want to use a specific seed in order to get a repeatable random
  sequence, pass an integer into the constructor:

  var m = new MersenneTwister(123);

  and that will always produce the same random sequence.

  Sean McCullough (banksean@gmail.com)
*/

/* 
   A C-program for MT19937, with initialization improved 2002/1/26.
   Coded by Takuji Nishimura and Makoto Matsumoto.

   Before using, initialize the state by using init_genrand(seed)  
   or init_by_array(init_key, key_length).

   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
   All rights reserved.                          

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

     1. Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

     2. Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

     3. The names of its contributors may not be used to endorse or promote 
        products derived from this software without specific prior written 
        permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


   Any feedback is very welcome.
   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/

var MersenneTwister = function(seed) {
  if (seed == undefined) {
    seed = new Date().getTime();
  } 
  /* Period parameters */  
  this.N = 624;
  this.M = 397;
  this.MATRIX_A = 0x9908b0df;   /* constant vector a */
  this.UPPER_MASK = 0x80000000; /* most significant w-r bits */
  this.LOWER_MASK = 0x7fffffff; /* least significant r bits */

  this.mt = new Array(this.N); /* the array for the state vector */
  this.mti=this.N+1; /* mti==N+1 means mt[N] is not initialized */

  this.init_genrand(seed);
}  

/* initializes mt[N] with a seed */
MersenneTwister.prototype.init_genrand = function(s) {
  this.mt[0] = s >>> 0;
  for (this.mti=1; this.mti<this.N; this.mti++) {
      var s = this.mt[this.mti-1] ^ (this.mt[this.mti-1] >>> 30);
   this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)
  + this.mti;
      /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
      /* In the previous versions, MSBs of the seed affect   */
      /* only MSBs of the array mt[].                        */
      /* 2002/01/09 modified by Makoto Matsumoto             */
      this.mt[this.mti] >>>= 0;
      /* for >32 bit machines */
  }
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
MersenneTwister.prototype.init_by_array = function(init_key, key_length) {
  var i, j, k;
  this.init_genrand(19650218);
  i=1; j=0;
  k = (this.N>key_length ? this.N : key_length);
  for (; k; k--) {
    var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30)
    this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525)))
      + init_key[j] + j; /* non linear */
    this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
    i++; j++;
    if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }
    if (j>=key_length) j=0;
  }
  for (k=this.N-1; k; k--) {
    var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30);
    this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941))
      - i; /* non linear */
    this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
    i++;
    if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }
  }

  this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */ 
}

/* generates a random number on [0,0xffffffff]-interval */
MersenneTwister.prototype.genrand_int32 = function() {
  var y;
  var mag01 = new Array(0x0, this.MATRIX_A);
  /* mag01[x] = x * MATRIX_A  for x=0,1 */

  if (this.mti >= this.N) { /* generate N words at one time */
    var kk;

    if (this.mti == this.N+1)   /* if init_genrand() has not been called, */
      this.init_genrand(5489); /* a default initial seed is used */

    for (kk=0;kk<this.N-this.M;kk++) {
      y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk+1]&this.LOWER_MASK);
      this.mt[kk] = this.mt[kk+this.M] ^ (y >>> 1) ^ mag01[y & 0x1];
    }
    for (;kk<this.N-1;kk++) {
      y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk+1]&this.LOWER_MASK);
      this.mt[kk] = this.mt[kk+(this.M-this.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
    }
    y = (this.mt[this.N-1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK);
    this.mt[this.N-1] = this.mt[this.M-1] ^ (y >>> 1) ^ mag01[y & 0x1];

    this.mti = 0;
  }

  y = this.mt[this.mti++];

  /* Tempering */
  y ^= (y >>> 11);
  y ^= (y << 7) & 0x9d2c5680;
  y ^= (y << 15) & 0xefc60000;
  y ^= (y >>> 18);

  return y >>> 0;
}

/* generates a random number on [0,0x7fffffff]-interval */
MersenneTwister.prototype.genrand_int31 = function() {
  return (this.genrand_int32()>>>1);
}

/* generates a random number on [0,1]-real-interval */
MersenneTwister.prototype.genrand_real1 = function() {
  return this.genrand_int32()*(1.0/4294967295.0); 
  /* divided by 2^32-1 */ 
}

/* generates a random number on [0,1)-real-interval */
MersenneTwister.prototype.random = function() {
  return this.genrand_int32()*(1.0/4294967296.0); 
  /* divided by 2^32 */
}

/* generates a random number on (0,1)-real-interval */
MersenneTwister.prototype.genrand_real3 = function() {
  return (this.genrand_int32() + 0.5)*(1.0/4294967296.0); 
  /* divided by 2^32 */
}

/* generates a random number on [0,1) with 53-bit resolution*/
MersenneTwister.prototype.genrand_res53 = function() { 
  var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6; 
  return(a*67108864.0+b)*(1.0/9007199254740992.0); 
} 

/* These real versions are due to Isaku Wada, 2002/01/09 added */

0

미리 생성 된 텍스처를 사용하거나 서버에 펄린 노이즈 텍스처 생성기를 넣고 펄린 노이즈 이미지를 쿼리하십시오.


이미 서버 에서이 작업을 수행하고 있으며 텍스처를 생성해야합니다.
Xeon06

서버 에서이 작업을 수행하는 경우 왜 자바 스크립트 요구 사항입니까? 다른 기술을 사용할 수 있습니까?
sam hocevar

@ SamHocevar 서버에서 JavaScript로하고 있습니다. Node.js.
Xeon06

@ Xenon06 : 만약 당신이 공연을한다면, 나는 당신이 네이티브 코드를 필요로한다고 생각합니다; 고맙게도 C ++로 Node.js 확장을 작성할 수 있습니다 .
sam hocevar

@ SamHocevar 쿨, 링크 주셔서 감사합니다, 나는 내 성능이 나쁜 경우 확인합니다
Xeon06
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.