perlin | A node.js perlin noise generator library | Runtime Evironment library
kandi X-RAY | perlin Summary
kandi X-RAY | perlin Summary
A node.js perlin noise generator library.
Support
Quality
Security
License
Reuse
Top functions reviewed by kandi - BETA
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample of perlin
perlin Key Features
perlin Examples and Code Snippets
Community Discussions
Trending Discussions on perlin
QUESTION
As seen on the picture, I need a math formula that calculate the red circled point with cartesian coordonate that will make equidistant lines. It is not simple trigonometry I guess...
My goal is to be able to calculate cartesian point around half of the circle and trace my lines from it.
Using p5js, I'll use random value from Perlin noise mixing it with sin or cos (whatever...) to trace my lines from those points. At start it's a math problem, the rest should be pretty easy for me since I already have a good base that work, but need to be optimized with this math.
Any clue ?
...ANSWER
Answered 2021-Jun-10 at 09:35This is a matter of converting between angles (polar coordinates) and Cartesian coordinates.
Here is a function calculateLines(x, y, radius, dist, angle, shift)
that takes the coordinate of the center, the radius of the circle, the distance between the lines, the angle of the lines (in radians), and the shift of the lines (perpendicular to their direction). It returns an array with segments. A segment is determined by a pair of coordinates, i.e. [x1, y1, x2, y2]
.
The below snippet allows you to play with these parameters and see the result interactively:
QUESTION
I'm trying to create a FBM texture using the module perlin-noise
, but it takes a very long time to execute. I've implemented multiprocessing
, only to find that the program was still running off a single core. I've tried looking for other people with the same problem, but most threads were 7+ years old and / or involved problems and solutions related to different OSs.
My OS is Windows 8.1, I have a quad-core CPU, and I'm running Python 3.9.2
Here is the program:
...ANSWER
Answered 2021-May-27 at 10:24Reason why it only use one Process is simple. You only passed 1-length list in Pool.map
.
What Pool(n).map(function, iterable)
does is, applying provided funtion to each element of provided iterable
(in this case, list
) with n
number of worker processes.
Since you only have 128 in nums
it's only creating one task thus no other processes are ever used.
Proper usage would look like this:
QUESTION
I'm making a game that will use terrain generation, so I am using the C# version of the FastNoise Lite library. However, it doesn't seem to be working as I want it to.
I have the following code which generates the TileMap:
...ANSWER
Answered 2021-May-24 at 17:49All I needed to do was add a fractal type:
QUESTION
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
} else {
cellDist.push(dis)
}
}
var ClosestCell = min(cellDist);
var ClosestCellpos;
for (var r = 0; r < cell.length / 2; r++) {
if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
ClosestCellpos = r;
break;
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
if (r < 100 && dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 || cpu[j * 4 + 2] > playerSize) {
var disXpos = cell[r * 2] - cpu[j * 4];
var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];
disXpos = map(disXpos, -100, 100, -1, 1);
disYpos = map(disYpos, -100, 100, -1, 1);
cpu[j * 4] += disXpos * amp;
cpu[j * 4 + 1] += disYpos * amp;
} else {
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
}
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
VS
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
...ANSWER
Answered 2021-May-04 at 01:49The reason the player instantly loses is because the code that the code that checks AI "cpu" distance to player doesn't work correctly.
QUESTION
I am using a software, pc/mrp, which appears to have a built-in Visual Fox Pro editor for FRX files. It also has an external usage of an ef file. Based on some usage of Google, the report designer seems standard, not custom. The ef file usage may be a custom thing. Now, I need to find a way to get access to a value from a SQL statement inside the report. The statement needs to run per-line in the report.
EF: This file has sections: ~in~ ~out~
In these sections, I can run code, but if there is a ~perline~ type section, I don't know how to access it. I can use the ~in~ to try to create a relationship between the databases, as shown in the following example:
...ANSWER
Answered 2021-Apr-30 at 20:21The sample code you show is doing something like a join with the SET RELATION command. To use SET RELATION, there has to be an index on the relevant field (expression) in the child table. So, if your table B has an index on PONO + LINE (or, if those are numeric, STR(PONO, length) + STR(LINE, length)), you can SET RELATION TO PONO + LINE INTO B, again, using the more complicated expression if necessary.
QUESTION
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
function setup() {
frameRate(999)
createCanvas(600, 450);
playerX = Xgrid / 2
playerY = Ygrid / 2;
}
function draw() {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10
Newcelltimer++;
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW)) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW)) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW)) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW)) {
playerX -= playerSpeed;
}
if (playerX < playerSize / 2 - Xgrid) {
playerX = playerSize / 2 - Xgrid
}
if (playerY < playerSize / 2 - Ygrid) {
playerY = playerSize / 2 - Ygrid
}
if (playerY > 2 * Ygrid - (playerSize / 2)) {
playerY = 2 * Ygrid - (playerSize / 2)
}
if (playerX > 2 * Xgrid - (playerSize / 2)) {
playerX = 2 * Xgrid - (playerSize / 2)
}
if (Newcelltimer % 30 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 100 == 0) {
cpu.push(random(-Xgrid, 2 * Xgrid), random(-Ygrid, 2 * Ygrid), 20)
}
for (var j = 0; j < cpu.length / 3; j++) {
fill(0, 255, 0, 100);
circle(NewposX,NewposY, cpu[j * 3 + 2])
}
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
stroke(0)
fill(255,255,0)
circle(playerX,playerY,playerSize);
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
noFill();
stroke(0, 0, 0)
rect(0 - Xgrid, 0 - Ygrid, 3 * Xgrid, 3 * Ygrid)
pop();
text("Your size is " + playerSize, 20, 20);
}
...ANSWER
Answered 2021-Apr-21 at 19:17You're question is a bit vague but it sounds like what you want to do is give the AI a goal I.E. some location in which it wants to go to and then use a simple pathfinder program to let it figure out the best direction to move in
QUESTION
UPDATE
I found out that the mesh center of the mesh object is not at 0,0,0. Does that do anything?
I have the following problem. I am generating a terrain from Perlin noise and that works fine. However, as soon as I try to instantiate any objects on it, some are spawned in the terrain area and some completely outside. When I reset the object's transform, it teleports to (0,0,0) as expected, but when I reset another object, that was not instantiated at runtime, the (0,0,0) is at a completely different location! I have no parent set to these objects and no parent set to the other object as well. Below is my code for generating the objects:
...ANSWER
Answered 2021-Apr-16 at 09:35I have no parent set to these objects and no parent set to the other object as well.
Actually, you do set parent:
QUESTION
ANSWER
Answered 2021-Apr-10 at 10:51First, do you need continuous values with a uniform distribution? Or do you just need to divide the region into N equally likely intervals?
If it's the latter, it's simple. Pre-generate a huge array (e.g. 0x10000000 in size) of noise evaluated at many random coordinates, sort the array, then divide the array into however many intervals you need. If you want to exploit the fact that noise's distribution is symmetric around zero, then for each value also add its sign flipped value to the array. The sorted value at the beginning of each interval is what you use in your boundary condition check.
If you actually need the continuous range of values, then you can try to fit a function to uniformize the noise output. I propose one method for modifying noise distributions here and it was tried out here. This was used to make 4D noise have a similar distribution to 3D noise, but it should work to uniformize too. Note that the formula involves an integral of a polynomial to integer powers that vary depending on your tuning value, but you can manually write evaluation functions for a handful of these cases (probably won't need more than k=3), then write the lerp logic on top of those. Then you can either use a mathematical or manual+visual metric for determining the best tuning value.
Obligatory noise algorithm selection note: Use good quality noise. That is, simplex-type noise with good gradient vector tables, or domain-rotated 3D+ Perlin. FastNoiseLite supports both (OpenSimplex2
or Perlin
+ SetRotationType3D(ImproveXYPlanes)
+ GetNoise(x, y, 0)
). Take it with a grain of salt when tutorials recommend Perlin noise with no caveats. Perlin is an older noise algo that, without the domain-rotation technique, produces a lot of squareness that is an entirely unnecessary compromise for most applications.
EDIT: Noticing that the domain in your image is 0 to 1. Most noise implementations, and indeed the library I linked, use the range -1 to 1. You can rescale after uniformization if you need to, though.
QUESTION
I am trying to use a map generator I made a few months ago. I remember it worked, I even showed it to some people, but now, it just doesn't work. I havent changed the python version, so this feels quite weird.
When I try to execute the code, I get this error:
...ANSWER
Answered 2021-Apr-06 at 12:31I don't have pygame
installed and did not want to install it because I do not know pygame
and am not really in a position to debug your program if you have other issues with your code other than the obvious things I saw. So I was not able to really test this. But I believe this is at least a good start in the right direction, if not perfect.
Instead of starting two processes, I have created a processing pool of size 2 to which I submit 2 "tasks." But what this allows me to do is to create the managed variables in my main process within the if __name__ == '__main__':
block and then to initialize each process in the pool with global variables initialized with these values using a special pool initializer function. The only other change I made is based on the comment I posted to your question. I have therefore renamed method apply_settings
to apply_our_settings
.
QUESTION
I'm trying to understand 2D Perlin noise from a visual point of view and I want to ask a couple of questions here to make sure I'm on the right track. I use WebGL and write custom shaders for rendering.
I start by calculating a dot product across one grid cell between a position vector from the center of the cell and one vertical vector and I get the gradient below (red is positive values and blue - negative). If I rotate the vector, it rotates the gradient:
Q1: The Wikipedia on "gradient noise" says "...a lattice of random gradients, dot products of which are then interpolated...". That's not correct, what creates actual gradients here is the dot operation itself, "gradient" vectors are just normal vectors, right?
Below are 3 different interpolations of 4 dots products between 4 random vectors and 4 position vectors calculated from each corner of each cell, the first one is simple average, the second is bilinear interpolation and the third is bilinear with smoothstep.
Q2: So what gives Perlin noise its organic blobby flowing look and feel is the interpolation method, rather that the gradients, in particular, the fact that bilinear interpolation is not linear but quadratic?
Thank you!
...ANSWER
Answered 2021-Apr-05 at 03:55A1: Technically correct. Usually I use the term "gradient vectors" which I think communicates the idea better, though sometimes I do call the vectors themselves "gradients". Maybe it's more confusing than I realize, you make a good point. Sometimes I call the actual gradient as you refer to it the "ramp", but "gradient" describes it well too.
A2: It's the way the gradients are combined, yes. Each grid vertex needs to contribute in some way to the noise around it, with its contribution falling off to zero smoothly outside of the range. The fade-curve lerp accomplishes this.
Obligatory note: If you're going to actually use noise in anything, I recommend either Simplex-type noise (with good gradient vector tables, and an "Open" noise if using it for 3D+), or domain-rotated 3D+ Perlin. Take it with a grain of salt when tutorials recommend Perlin noise with no caveats. Perlin is an older noise algo that, without anything done specifically to correct it, produces a lot of squareness that is an entirely unnecessary compromise for most applications. I suggest using FastNoiseLite with these steps or these domain-rotated Perlin evaluators.
If you want to implement 2D simplex yourself, I wrote this answer a while back where I described a process.
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install perlin
Support
Reuse Trending Solutions
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesStay Updated
Subscribe to our newsletter for trending solutions and developer bootcamps
Share this Page