Tôi đang nghiên cứu một vài cách triển khai khác nhau cho tiếng ồn mạch lạc (tôi biết có thư viện, nhưng điều này chủ yếu là do sự chỉnh sửa và tò mò của riêng tôi) và cách bạn có thể sử dụng nó. Tôi có điều tiếng ồn Perlin gốc.Phạm vi đầu ra của nhiễu Perlin
Theo this frequently linked Math FAQ, phạm vi đầu ra sẽ nằm trong khoảng từ -1
và 1
, nhưng tôi không hiểu cách giá trị nằm trong phạm vi đó.
Như tôi đã hiểu, thuật toán về cơ bản là: mỗi điểm lưới có một vector gradient ngẫu nhiên liên quan có chiều dài 1
. Sau đó, đối với mỗi điểm, đối với tất cả bốn điểm lưới xung quanh, bạn tính toán sản phẩm chấm của gradient ngẫu nhiên và vectơ đi từ điểm lưới đó. Sau đó, bạn sử dụng một đường cong dễ dàng ưa thích và nội suy tuyến tính để giảm giá trị đó xuống một giá trị. Tuy nhiên, đây là vấn đề của tôi: đôi khi, các sản phẩm này sẽ nằm ngoài phạm vi [-1, 1]
và do bạn thực hiện nội suy tuyến tính cuối cùng giữa các sản phẩm chấm, điều đó có nghĩa là giá trị cuối cùng sẽ, đôi khi, nằm ngoài phạm vi [-1, 1]
? Ví dụ:
Ví dụ: một trong các vectơ ngẫu nhiên là (sqrt(2)/2, sqrt(2)/2)
(có chiều dài 1) và (0.8, 0.8)
(nằm trong ô vuông đơn vị), bạn sẽ nhận được kết quả là khoảng 1.131
. Nếu giá trị đó được sử dụng trong nội suy tuyến tính, hoàn toàn có thể là giá trị được tạo sẽ lớn hơn 1
. Và, quả thực, với việc triển khai thẳng tiến của tôi, điều đó xảy ra khá thường xuyên.
Tôi có thiếu gì đó ở đây không?
Để tham khảo, đây là mã của tôi bằng Java. Vec
là một lớp đơn giản để làm số học vectơ 2d đơn giản, fade()
là đường cong dễ dàng, lerp()
là nội suy tuyến tính và gradient(x, y)
cung cấp cho bạn độ dốc cho điểm lưới đó là Vec
. Biến gridSize
mang đến cho bạn kích thước của lưới bằng pixel (nó có kiểu 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);
}
Edit: đây là đoạn code để tạo ra các gradient ngẫu nhiên:
double theta = gen.nextDouble() * 2 * Math.PI;
gradients[i] = new Vec(Math.cos(theta), Math.sin(theta));
đâu gen
là một java.util.Random
.
Cảm ơn sự giúp đỡ của bạn! Điều đó đã sửa nó. – Oskar