Badam kilka różnych implementacji dla spójnego szumu (wiem, że istnieją biblioteki, ale to głównie dla mojego własnego zbudowania i ciekawości) i jak możesz z niego korzystać, i jest jeden problem Mam z oryginalnym szumem Perlina.Zasięg wyjściowy szumu Perlina
Zgodnie z , zakres wyjściowy będzie wynosił od -1
i 1
, ale nie rozumiem, jak wartość ma być w tym zakresie.
Jak rozumiem, algorytm jest w zasadzie taki: każdy punkt siatki ma powiązany losowy wektor gradientu o długości 1
. Następnie, dla każdego punktu, dla wszystkich czterech otaczających punktów siatki, obliczysz iloczyn skalarny gradientu losowego i wektora przechodzącego z tego punktu siatki. Następnie użyjesz fantazyjnej krzywej łatwości i interpolacji liniowej, aby obniżyć ją do jednej wartości.
Ale, tu jest mój problem: te produkty z wykresem czasami są poza zasięgiem [-1, 1]
, a ponieważ dokonujesz interpolacji liniowej ostatecznie pomiędzy produktami kropkowymi, nie oznacza to, że ostateczna wartość będzie, czasami poza zasięgiem [-1, 1]
?
Załóżmy na przykład, że jeden z losowych wektorów jest (sqrt(2)/2, sqrt(2)/2)
(który ma długość 1) oraz (0.8, 0.8)
(który jest na placu jednostki), można uzyskać wynik około 1.131
. Jeśli ta wartość jest używana w interpolacji liniowej, jest całkowicie możliwe, że wygenerowana wartość będzie większa niż 1
. I rzeczywiście, z moją prostą implementacją zdarza się to dość często.
Czy tu czegoś brakuje?
Dla odniesienia, oto mój kod w Javie. Vec
to prosta klasa do wykonania prostej arytmetyki wektorowej 2d, fade()
jest krzywa łatwości, lerp()
jest interpolacją liniową, a gradient(x, y)
podaje gradient dla tego punktu siatki jako Vec
. Zmienna gridSize
daje rozmiar siatki w pikselach (ma typ double):
public double getPoint(int x, int y) {
Vec p = new Vec(x/gridSize, y/gridSize);
Vec d = new Vec(Math.floor(p.x), Math.floor(p.y));
int x0 = (int)d.x,
y0 = (int)d.x;
double d00 = gradient(x0 , y0 ).dot(p.sub(x0 , y0 )),
d01 = gradient(x0 , y0 + 1).dot(p.sub(x0 , y0 + 1)),
d10 = gradient(x0 + 1, y0 ).dot(p.sub(x0 + 1, y0 )),
d11 = gradient(x0 + 1, y0 + 1).dot(p.sub(x0 + 1, y0 + 1));
double fadeX = fade(p.x - d.x),
fadeY = fade(p.y - d.y);
double i1 = lerp(fadeX, d00, d10),
i2 = lerp(fadeX, d01, d11);
return lerp(fadeY, i1, i2);
}
Edycja: Oto kod do generowania losowych gradientów:
double theta = gen.nextDouble() * 2 * Math.PI;
gradients[i] = new Vec(Math.cos(theta), Math.sin(theta));
Gdzie gen
jest java.util.Random
.
Dzięki za pomoc! To naprawiło to. – Oskar