Skip to content

Commit 37519dc

Browse files
committed
perf(noise): flat gradient tables and hoisted worley hashes
Store the permutation as a Uint8Array and the 3D/4D gradients as flat Float64Array triples and quads, so each corner contribution indexes the table directly instead of chasing a nested Vec3[]/Vec4[] pointer. Worley samplers hoist the y and z hash stages out of the innermost loop. Outputs are bit-identical to the previous implementation. Measured with labs against the full-suite baseline (8 fresh-process blocks, p < .001 on every bench, all output snapshots matched): perlin2d -42% perlin3d -39% simplex2d -17% simplex3d -20% simplex4d -13% worley2d -41% worley3d -54% fbm x5 -6% curl2 -20% The Permutation type shape changed: gradP/gradP4 are replaced by grad3/grad4.
1 parent a0778d8 commit 37519dc

10 files changed

Lines changed: 163 additions & 137 deletions

File tree

‎API.md‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ overview, installation, and examples, see the [README](./README.md).
4242
- <a id="round"></a>`round(a: number): number` — Symmetric round
4343
- <a id="fade"></a>`fade(t: number)` — Ease-in-out, goes to -Infinite before 0 and Infinite after 1
4444
- <a id="lerp"></a>`lerp(v0: number, v1: number, t: number)`
45+
- <a id="lagrange"></a>`lagrange(v0: number, v1: number, v2: number, t: number)`
46+
- <a id="binomial"></a>`binomial(n: number, k: number): number`
4547
- <a id="clamp"></a>`clamp(value: number, min: number, max: number): number` — Clamp a value between min and max
4648
- <a id="repeat"></a>`repeat(t: number, length: number): number` — Loops `t` so that it is never larger than `length` and never smaller than 0.
4749
- <a id="remap"></a>`remap(number: number, inLow: number, inHigh: number, outLow: number, outHigh: number): number` — Remaps a number from one range to another.
@@ -102,6 +104,7 @@ import { vec2 } from 'math';
102104
- `vec2.dot(a: Vec2, b: Vec2): number` — Calculates the dot product of two vec2's
103105
- `vec2.cross(out: Vec3, a: Vec2, b: Vec2): Vec3` — Computes the cross product of two vec2's
104106
- `vec2.lerp(out: Vec2, a: Vec2, b: Vec2, t: number): Vec2` — Performs a linear interpolation between two vec2's
107+
- `vec2.lagrange(out: Vec2, a: Vec2, b: Vec2, c: Vec2, t: number): Vec2` — Quadratic interpolation through three vectors using Lagrange interpolation.
105108

106109
**Transform**
107110

@@ -175,6 +178,7 @@ import { vec3 } from 'math';
175178
- `vec3.cross(out: Vec3, a: Vec3, b: Vec3): Vec3` — Computes the cross product of two vec3's
176179
- `vec3.perpendicular(out: Vec3, a: Vec3): Vec3` — Calculates a normalized perpendicular vector to the given vector.
177180
- `vec3.lerp(out: Vec3, a: Vec3, b: Vec3, t: number): Vec3` — Performs a linear interpolation between two vec3's
181+
- `vec3.lagrange(out: Vec3, a: Vec3, b: Vec3, c: Vec3, t: number): Vec3` — Quadratic interpolation through three vectors using Lagrange interpolation.
178182
- `vec3.slerp(out: Vec3, a: Vec3, b: Vec3, t: number): Vec3` — Performs a spherical linear interpolation between two vec3's
179183
- `vec3.hermite(out: Vec3, a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number): Vec3` — Performs a hermite interpolation with two control points
180184
- `vec3.bezier(out: Vec3, a: Vec3, b: Vec3, c: Vec3, d: Vec3, t: number): Vec3` — Performs a bezier interpolation with two control points
@@ -249,6 +253,7 @@ import { vec4 } from 'math';
249253
- `vec4.dot(a: Vec4, b: Vec4): number` — Calculates the dot product of two vec4's
250254
- `vec4.cross(out: Vec4, u: Vec4, v: Vec4, w: Vec4): Vec4` — Returns the cross-product of three vectors in a 4-dimensional space
251255
- `vec4.lerp(out: Vec4, a: Vec4, b: Vec4, t: number): Vec4` — Performs a linear interpolation between two vec4's
256+
- `vec4.lagrange(out: Vec4, a: Vec4, b: Vec4, c: Vec4, t: number): Vec4` — Quadratic interpolation through three vectors using Lagrange interpolation.
252257

253258
**Transform**
254259

@@ -1256,7 +1261,7 @@ import { random } from 'math/random';
12561261

12571262
**Types**
12581263

1259-
- `type Permutation = { perm: number[]; gradP: Vec3[]; gradP4: Vec4[]; }` — Seeded permutation and gradient tables that back a noise generator.
1264+
- `type Permutation = { perm: Uint8Array; grad3: Float64Array; grad4: Float64Array; }` — Seeded permutation and gradient tables that back a noise generator.
12601265

12611266
**Operations**
12621267

@@ -1286,7 +1291,7 @@ import { perlin2d } from 'math/noise';
12861291

12871292
**Operations**
12881293

1289-
- `perlin2d.sample({ perm, gradP }: Perlin2DGenerator, x: number, y: number): number` — Samples 2D Perlin noise.
1294+
- `perlin2d.sample({ perm, grad3 }: Perlin2DGenerator, x: number, y: number): number` — Samples 2D Perlin noise.
12901295

12911296
<a id="api-math-noise-perlin3d"></a>
12921297

@@ -1306,7 +1311,7 @@ import { perlin3d } from 'math/noise';
13061311

13071312
**Operations**
13081313

1309-
- `perlin3d.sample({ perm, gradP }: Perlin3DGenerator, x: number, y: number, z: number): number` — Samples 3D Perlin noise.
1314+
- `perlin3d.sample({ perm, grad3 }: Perlin3DGenerator, x: number, y: number, z: number): number` — Samples 3D Perlin noise.
13101315

13111316
<a id="api-math-noise-simplex2d"></a>
13121317

@@ -1326,7 +1331,7 @@ import { simplex2d } from 'math/noise';
13261331

13271332
**Operations**
13281333

1329-
- `simplex2d.sample({ perm, gradP }: Simplex2DGenerator, x: number, y: number): number` — Samples 2D simplex noise, returning a value in the interval [-1, 1].
1334+
- `simplex2d.sample({ perm, grad3 }: Simplex2DGenerator, x: number, y: number): number` — Samples 2D simplex noise, returning a value in the interval [-1, 1].
13301335

13311336
<a id="api-math-noise-simplex3d"></a>
13321337

@@ -1346,7 +1351,7 @@ import { simplex3d } from 'math/noise';
13461351

13471352
**Operations**
13481353

1349-
- `simplex3d.sample({ perm, gradP }: Simplex3DGenerator, x: number, y: number, z: number): number` — Samples 3D simplex noise, returning a value in the interval [-1, 1].
1354+
- `simplex3d.sample({ perm, grad3 }: Simplex3DGenerator, x: number, y: number, z: number): number` — Samples 3D simplex noise, returning a value in the interval [-1, 1].
13501355

13511356
<a id="api-math-noise-simplex4d"></a>
13521357

@@ -1366,7 +1371,7 @@ import { simplex4d } from 'math/noise';
13661371

13671372
**Operations**
13681373

1369-
- `simplex4d.sample({ perm, gradP4 }: Simplex4DGenerator, x: number, y: number, z: number, w: number): number` — Samples 4D simplex noise, returning a value in the interval [-1, 1].
1374+
- `simplex4d.sample({ perm, grad4 }: Simplex4DGenerator, x: number, y: number, z: number, w: number): number` — Samples 4D simplex noise, returning a value in the interval [-1, 1].
13701375

13711376
<a id="api-math-noise-worley2d"></a>
13721377

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ math is a collection of math helpers for graphics and simulations.
1515

1616
| Import | Description | Contents |
1717
| --- | --- | --- |
18-
| [`math`](API.md#api-math) | Vectors, quaternions, euler angles & matrices | [`vec2`](API.md#api-math-vec2) [`vec3`](API.md#api-math-vec3) [`vec4`](API.md#api-math-vec4) [`euler`](API.md#api-math-euler) [`quat`](API.md#api-math-quat) [`quat2`](API.md#api-math-quat2) [`mat2`](API.md#api-math-mat2) [`mat2d`](API.md#api-math-mat2d) [`mat3`](API.md#api-math-mat3) [`mat4`](API.md#api-math-mat4) [`spherical`](API.md#api-math-spherical) [`polar`](API.md#api-math-polar) [`EPSILON`](API.md#epsilon) [`round`](API.md#round) [`equals`](API.md#equals) [`fade`](API.md#fade) [`lerp`](API.md#lerp) [`clamp`](API.md#clamp) [`repeat`](API.md#repeat) [`remap`](API.md#remap) [`remapClamp`](API.md#remapclamp) [`DEGREES_TO_RADIANS`](API.md#degrees_to_radians) [`RADIANS_TO_DEGREES`](API.md#radians_to_degrees) [`degreesToRadians`](API.md#degreestoradians) [`radiansToDegrees`](API.md#radianstodegrees) [`wrapAngle`](API.md#wrapangle) [`deltaAngle`](API.md#deltaangle) |
18+
| [`math`](API.md#api-math) | Vectors, quaternions, euler angles & matrices | [`vec2`](API.md#api-math-vec2) [`vec3`](API.md#api-math-vec3) [`vec4`](API.md#api-math-vec4) [`euler`](API.md#api-math-euler) [`quat`](API.md#api-math-quat) [`quat2`](API.md#api-math-quat2) [`mat2`](API.md#api-math-mat2) [`mat2d`](API.md#api-math-mat2d) [`mat3`](API.md#api-math-mat3) [`mat4`](API.md#api-math-mat4) [`spherical`](API.md#api-math-spherical) [`polar`](API.md#api-math-polar) [`EPSILON`](API.md#epsilon) [`round`](API.md#round) [`equals`](API.md#equals) [`fade`](API.md#fade) [`lerp`](API.md#lerp) [`lagrange`](API.md#lagrange) [`binomial`](API.md#binomial) [`clamp`](API.md#clamp) [`repeat`](API.md#repeat) [`remap`](API.md#remap) [`remapClamp`](API.md#remapclamp) [`DEGREES_TO_RADIANS`](API.md#degrees_to_radians) [`RADIANS_TO_DEGREES`](API.md#radians_to_degrees) [`degreesToRadians`](API.md#degreestoradians) [`radiansToDegrees`](API.md#radianstodegrees) [`wrapAngle`](API.md#wrapangle) [`deltaAngle`](API.md#deltaangle) |
1919
| [`math/shapes`](API.md#api-math-shapes) | Shape primitives & spatial queries | [`box2`](API.md#api-math-shapes-box2) [`box3`](API.md#api-math-shapes-box3) [`obb3`](API.md#api-math-shapes-obb3) [`plane3`](API.md#api-math-shapes-plane3) [`sphere`](API.md#api-math-shapes-sphere) [`circle`](API.md#api-math-shapes-circle) [`segment2`](API.md#api-math-shapes-segment2) [`polygon2`](API.md#api-math-shapes-polygon2) [`triangle2`](API.md#api-math-shapes-triangle2) [`triangle3`](API.md#api-math-shapes-triangle3) [`raycast3`](API.md#api-math-shapes-raycast3) [`frustum`](API.md#api-math-shapes-frustum) |
2020
| [`math/geometry`](API.md#api-math-geometry) | Geometric algorithms | [`circumcircle`](API.md#circumcircle) [`decomposePolygon2Quick`](API.md#decomposepolygon2quick) [`decomposePolygon2Quality`](API.md#decomposepolygon2quality) [`triangulatePolygon2`](API.md#triangulatepolygon2) [`quickhull2`](API.md#quickhull2) [`quickhull3`](API.md#quickhull3) |
2121
| [`math/time`](API.md#api-math-time) | Easing & spring animation | [`easing`](API.md#api-math-time-easing) [`spring`](API.md#api-math-time-spring) [`spring2`](API.md#api-math-time-spring2) [`spring3`](API.md#api-math-time-spring3) [`spring4`](API.md#api-math-time-spring4) |

‎src/noise/perlin2d.ts‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { fade, lerp } from '../core/scalar';
2-
import { createPermutation, dot2, type Permutation } from './permutation';
2+
import { createPermutation, type Permutation } from './permutation';
33

44
/** A seeded 2D Perlin noise generator. Create one with {@link create}. */
55
export type Perlin2DGenerator = Permutation;
@@ -22,7 +22,7 @@ export function create(seed: number): Perlin2DGenerator {
2222
* @param y Y coordinate
2323
* @returns The noise value at (x, y)
2424
*/
25-
export function sample({ perm, gradP }: Perlin2DGenerator, x: number, y: number): number {
25+
export function sample({ perm, grad3 }: Perlin2DGenerator, x: number, y: number): number {
2626
// Find unit grid cell containing point
2727
let X = Math.floor(x);
2828
let Y = Math.floor(y);
@@ -33,11 +33,20 @@ export function sample({ perm, gradP }: Perlin2DGenerator, x: number, y: number)
3333
X = X & 255;
3434
Y = Y & 255;
3535

36+
const x1 = x - 1;
37+
const y1 = y - 1;
38+
39+
// Hashed gradient indices of the four corners (flat xyz triples in grad3)
40+
const g00 = (X + perm[Y]) * 3;
41+
const g01 = (X + perm[Y + 1]) * 3;
42+
const g10 = (X + 1 + perm[Y]) * 3;
43+
const g11 = (X + 1 + perm[Y + 1]) * 3;
44+
3645
// Calculate noise contributions from each of the four corners
37-
const n00 = dot2(gradP[X + perm[Y]], x, y);
38-
const n01 = dot2(gradP[X + perm[Y + 1]], x, y - 1);
39-
const n10 = dot2(gradP[X + 1 + perm[Y]], x - 1, y);
40-
const n11 = dot2(gradP[X + 1 + perm[Y + 1]], x - 1, y - 1);
46+
const n00 = grad3[g00] * x + grad3[g00 + 1] * y;
47+
const n01 = grad3[g01] * x + grad3[g01 + 1] * y1;
48+
const n10 = grad3[g10] * x1 + grad3[g10 + 1] * y;
49+
const n11 = grad3[g11] * x1 + grad3[g11 + 1] * y1;
4150

4251
// Compute the fade curve value for x
4352
const u = fade(x);

‎src/noise/perlin3d.ts‎

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { fade, lerp } from '../core/scalar';
2-
import { createPermutation, dot3, type Permutation } from './permutation';
2+
import { createPermutation, type Permutation } from './permutation';
33

44
/** A seeded 3D Perlin noise generator. Create one with {@link create}. */
55
export type Perlin3DGenerator = Permutation;
@@ -23,7 +23,7 @@ export function create(seed: number): Perlin3DGenerator {
2323
* @param z Z coordinate
2424
* @returns The noise value at (x, y, z)
2525
*/
26-
export function sample({ perm, gradP }: Perlin3DGenerator, x: number, y: number, z: number): number {
26+
export function sample({ perm, grad3 }: Perlin3DGenerator, x: number, y: number, z: number): number {
2727
// Find unit grid cell containing point
2828
let X = Math.floor(x);
2929
let Y = Math.floor(y);
@@ -37,15 +37,37 @@ export function sample({ perm, gradP }: Perlin3DGenerator, x: number, y: number,
3737
Y = Y & 255;
3838
Z = Z & 255;
3939

40+
const x1 = x - 1;
41+
const y1 = y - 1;
42+
const z1 = z - 1;
43+
44+
// Hash the Z and Y rows once; each corner then only needs one more lookup
45+
const pz0 = perm[Z];
46+
const pz1 = perm[Z + 1];
47+
const py00 = perm[Y + pz0];
48+
const py01 = perm[Y + pz1];
49+
const py10 = perm[Y + 1 + pz0];
50+
const py11 = perm[Y + 1 + pz1];
51+
52+
// Hashed gradient indices of the eight corners (flat xyz triples in grad3)
53+
const g000 = (X + py00) * 3;
54+
const g001 = (X + py01) * 3;
55+
const g010 = (X + py10) * 3;
56+
const g011 = (X + py11) * 3;
57+
const g100 = (X + 1 + py00) * 3;
58+
const g101 = (X + 1 + py01) * 3;
59+
const g110 = (X + 1 + py10) * 3;
60+
const g111 = (X + 1 + py11) * 3;
61+
4062
// Calculate noise contributions from each of the eight corners
41-
const n000 = dot3(gradP[X + perm[Y + perm[Z]]], x, y, z);
42-
const n001 = dot3(gradP[X + perm[Y + perm[Z + 1]]], x, y, z - 1);
43-
const n010 = dot3(gradP[X + perm[Y + 1 + perm[Z]]], x, y - 1, z);
44-
const n011 = dot3(gradP[X + perm[Y + 1 + perm[Z + 1]]], x, y - 1, z - 1);
45-
const n100 = dot3(gradP[X + 1 + perm[Y + perm[Z]]], x - 1, y, z);
46-
const n101 = dot3(gradP[X + 1 + perm[Y + perm[Z + 1]]], x - 1, y, z - 1);
47-
const n110 = dot3(gradP[X + 1 + perm[Y + 1 + perm[Z]]], x - 1, y - 1, z);
48-
const n111 = dot3(gradP[X + 1 + perm[Y + 1 + perm[Z + 1]]], x - 1, y - 1, z - 1);
63+
const n000 = grad3[g000] * x + grad3[g000 + 1] * y + grad3[g000 + 2] * z;
64+
const n001 = grad3[g001] * x + grad3[g001 + 1] * y + grad3[g001 + 2] * z1;
65+
const n010 = grad3[g010] * x + grad3[g010 + 1] * y1 + grad3[g010 + 2] * z;
66+
const n011 = grad3[g011] * x + grad3[g011 + 1] * y1 + grad3[g011 + 2] * z1;
67+
const n100 = grad3[g100] * x1 + grad3[g100 + 1] * y + grad3[g100 + 2] * z;
68+
const n101 = grad3[g101] * x1 + grad3[g101 + 1] * y + grad3[g101 + 2] * z1;
69+
const n110 = grad3[g110] * x1 + grad3[g110 + 1] * y1 + grad3[g110 + 2] * z;
70+
const n111 = grad3[g111] * x1 + grad3[g111 + 1] * y1 + grad3[g111 + 2] * z1;
4971

5072
// Compute the fade curve value for x, y, z
5173
const u = fade(x);

‎src/noise/permutation.ts‎

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import type { Vec3 } from '../core/vec3';
2-
import type { Vec4 } from '../core/vec4';
3-
41
// Adapated from https://github.com/josephg/noisejs
52
//
63
// ```
@@ -22,17 +19,16 @@ import type { Vec4 } from '../core/vec4';
2219
* Seeded permutation and gradient tables that back a noise generator.
2320
*
2421
* All noise variants (simplex/perlin, 2D/3D/4D) share this same table shape, so
25-
* each generator type is a structural alias of this. `gradP` holds the 3D
26-
* gradients (used by 2D and 3D noise); `gradP4` holds the 4D gradients.
22+
* each generator type is a structural alias of this. `perm` is the doubled
23+
* (512 entry) permutation table. `grad3` holds the 3D gradient for each
24+
* permutation index as flat xyz triples (used by 2D and 3D noise), and `grad4`
25+
* holds the 4D gradient for each index as flat xyzw quads. Flat typed arrays
26+
* keep sampling free of nested array loads and allocation.
2727
*/
28-
export type Permutation = { perm: number[]; gradP: Vec3[]; gradP4: Vec4[] };
29-
30-
export const dot2 = (grad: Vec3, x: number, y: number) => grad[0] * x + grad[1] * y;
31-
export const dot3 = (grad: Vec3, x: number, y: number, z: number) => grad[0] * x + grad[1] * y + grad[2] * z;
32-
export const dot4 = (grad: Vec4, x: number, y: number, z: number, w: number) =>
33-
grad[0] * x + grad[1] * y + grad[2] * z + grad[3] * w;
28+
export type Permutation = { perm: Uint8Array; grad3: Float64Array; grad4: Float64Array };
3429

35-
const grad3: Vec3[] = [
30+
// the 12 3D gradient directions (edges of a cube), indexed by perm value % 12
31+
const GRAD3: number[][] = [
3632
[1, 1, 0],
3733
[-1, 1, 0],
3834
[1, -1, 0],
@@ -48,7 +44,7 @@ const grad3: Vec3[] = [
4844
];
4945

5046
// the 32 4D gradient directions (edges of a hypercube), indexed by perm value % 32
51-
const grad4: Vec4[] = [
47+
const GRAD4: number[][] = [
5248
[0, 1, 1, 1],
5349
[0, 1, 1, -1],
5450
[0, 1, -1, 1],
@@ -114,9 +110,9 @@ export function createPermutation(seed: number): Permutation {
114110
}
115111

116112
// To remove the need for index wrapping, double the permutation table length
117-
const perm: number[] = new Array(512);
118-
const gradP: Vec3[] = new Array(512);
119-
const gradP4: Vec4[] = new Array(512);
113+
const perm = new Uint8Array(512);
114+
const grad3 = new Float64Array(512 * 3);
115+
const grad4 = new Float64Array(512 * 4);
120116

121117
for (let i = 0; i < 256; i++) {
122118
let v: number;
@@ -127,9 +123,16 @@ export function createPermutation(seed: number): Permutation {
127123
}
128124

129125
perm[i] = perm[i + 256] = v;
130-
gradP[i] = gradP[i + 256] = grad3[v % 12];
131-
gradP4[i] = gradP4[i + 256] = grad4[v % 32];
126+
127+
const g3 = GRAD3[v % 12];
128+
const g4 = GRAD4[v % 32];
129+
for (let k = 0; k < 3; k++) {
130+
grad3[i * 3 + k] = grad3[(i + 256) * 3 + k] = g3[k];
131+
}
132+
for (let k = 0; k < 4; k++) {
133+
grad4[i * 4 + k] = grad4[(i + 256) * 4 + k] = g4[k];
134+
}
132135
}
133136

134-
return { perm, gradP, gradP4 };
137+
return { perm, grad3, grad4 };
135138
}

‎src/noise/simplex2d.ts‎

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createPermutation, dot2, type Permutation } from './permutation';
1+
import { createPermutation, type Permutation } from './permutation';
22

33
/** A seeded 2D simplex noise generator. Create one with {@link create}. */
44
export type Simplex2DGenerator = Permutation;
@@ -25,10 +25,7 @@ export function create(seed: number): Simplex2DGenerator {
2525
* @param y Y coordinate
2626
* @returns The noise value at (x, y)
2727
*/
28-
export function sample({ perm, gradP }: Simplex2DGenerator, x: number, y: number): number {
29-
let n0: number;
30-
let n1: number;
31-
let n2: number; // Noise contributions from the three corners
28+
export function sample({ perm, grad3 }: Simplex2DGenerator, x: number, y: number): number {
3229
// Skew the input space to determine which simplex cell we're in
3330
const s = (x + y) * F2; // Hairy factor for 2D
3431
let i = Math.floor(x + s);
@@ -57,32 +54,30 @@ export function sample({ perm, gradP }: Simplex2DGenerator, x: number, y: number
5754
const x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords
5855
const y2 = y0 - 1 + 2 * G2;
5956
// Work out the hashed gradient indices of the three simplex corners
57+
// (flat xyz triples in grad3; only x and y are used for 2D)
6058
i &= 255;
6159
j &= 255;
62-
const gi0 = gradP[i + perm[j]];
63-
const gi1 = gradP[i + i1 + perm[j + j1]];
64-
const gi2 = gradP[i + 1 + perm[j + 1]];
60+
const gi0 = (i + perm[j]) * 3;
61+
const gi1 = (i + i1 + perm[j + j1]) * 3;
62+
const gi2 = (i + 1 + perm[j + 1]) * 3;
6563
// Calculate the contribution from the three corners
64+
let n0 = 0;
65+
let n1 = 0;
66+
let n2 = 0;
6667
let t0 = 0.5 - x0 * x0 - y0 * y0;
67-
if (t0 < 0) {
68-
n0 = 0;
69-
} else {
68+
if (t0 >= 0) {
7069
t0 *= t0;
71-
n0 = t0 * t0 * dot2(gi0, x0, y0); // (x,y) of grad3 used for 2D gradient
70+
n0 = t0 * t0 * (grad3[gi0] * x0 + grad3[gi0 + 1] * y0);
7271
}
7372
let t1 = 0.5 - x1 * x1 - y1 * y1;
74-
if (t1 < 0) {
75-
n1 = 0;
76-
} else {
73+
if (t1 >= 0) {
7774
t1 *= t1;
78-
n1 = t1 * t1 * dot2(gi1, x1, y1);
75+
n1 = t1 * t1 * (grad3[gi1] * x1 + grad3[gi1 + 1] * y1);
7976
}
8077
let t2 = 0.5 - x2 * x2 - y2 * y2;
81-
if (t2 < 0) {
82-
n2 = 0;
83-
} else {
78+
if (t2 >= 0) {
8479
t2 *= t2;
85-
n2 = t2 * t2 * dot2(gi2, x2, y2);
80+
n2 = t2 * t2 * (grad3[gi2] * x2 + grad3[gi2 + 1] * y2);
8681
}
8782
// Add contributions from each corner to get the final noise value.
8883
// The result is scaled to return values in the interval [-1,1].

0 commit comments

Comments
 (0)