Sau khi đọc câu trả lời của Peachykeen và thực hiện một số nghiên cứu riêng (trên) trên internet, tôi đã tìm thấy giải pháp sau đây để làm việc cho tôi.
Với thực hiện của tôi Perlin tiếng ồn, sử dụng một phạm vi giá trị của [0,0 .. 1,0] cho sét nút con đường hiệu quả nhất, đi qua các giá trị (double) M/(double) N cho nút M đến Perlin chức năng tiếng ồn.
Để có hàm tiếng ồn F 'trả về cùng giá trị cho nút 0 và nút N-1, công thức sau có thể được áp dụng: F' (M) = ((M - N) * F (N) + N * F (N - M))/M. Để có các đường tắt tia chớp bắt đầu và kết thúc bằng 0, bạn chỉ cần trừ F '(0) khỏi tất cả các đường tắt tia chớp sau khi tính toán đường đi. Để ngẫu nhiên con đường sét, trước khi tính toán bù trừ cho mỗi nút đường dẫn, một R bù ngẫu nhiên có thể được tính toán và thêm vào các giá trị được chuyển đến hàm nhiễu, sao cho bù đắp của nút O = F '(N + R). Để tạo hiệu ứng cho một tia chớp, cần phải tính hai đường dẫn sét (khung bắt đầu và kết thúc), và sau đó mỗi đỉnh đường dẫn phải được lerped giữa vị trí bắt đầu và kết thúc của nó. Khi đã đạt đến khung kết thúc, khung kết thúc sẽ trở thành khung bắt đầu và một khung kết thúc mới được tính toán. Đối với một đường dẫn 3D, cho mỗi nút đường dẫn N hai vector bù có thể được tính vuông góc với đường dẫn tại nút N và mỗi khác, và có thể được chia tỷ lệ với hai giá trị tạp âm 1D Perlin để lerp vị trí nút từ vị trí khung đầu đến cuối . Điều đó có thể rẻ hơn so với làm nhiễu 3D Perlin và hoạt động khá tốt trong ứng dụng của tôi.
Đây là triển khai thực hiện của tôi về tiêu chuẩn tiếng ồn 1D Perlin như một tài liệu tham khảo (một số nội dung là ảo bởi vì tôi đang sử dụng này như là cơ sở cho việc cải thiện tiếng ồn Perlin, cho phép sử dụng tiêu chuẩn hoặc được cải thiện tiếng ồn Perlin trong một ứng dụng mô hình chiến lược. mã này đã được đơn giản hóa phần nào cũng như để làm cho nó ngắn gọn hơn cho xuất bản nó ở đây):
header file:
#ifndef __PERLIN_H
#define __PERLIN_H
class CPerlin {
private:
int m_randomize;
protected:
double m_amplitude;
double m_persistence;
int m_octaves;
public:
virtual void Setup (double amplitude, double persistence, int octaves, int randomize = -1);
double ComputeNoise (double x);
protected:
double LinearInterpolate (double a, double b, double x);
double CosineInterpolate (double a, double b, double x);
double CubicInterpolate (double v0, double v1, double v2, double v3, double x);
double Noise (int v);
double SmoothedNoise (int x);
virtual double InterpolatedNoise (double x);
};
#endif //__PERLIN_H
thực hiện:
#include <math.h>
#include <stdlib.h>
#include "perlin.h"
#define INTERPOLATION_METHOD 1
#ifndef Pi
# define Pi 3.141592653589793240
#endif
inline double CPerlin::Noise (int n) {
n = (n << 13)^n;
return 1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0;
}
double CPerlin::LinearInterpolate (double a, double b, double x) {
return a * (1.0 - x) + b * x;
}
double CPerlin::CosineInterpolate (double a, double b, double x) {
double f = (1.0 - cos (x * Pi)) * 0.5;
return a * (1.0 - f) + b * f;
}
double CPerlin::CubicInterpolate (double v0, double v1, double v2, double v3, double x) {
double p = (v3 - v2) - (v0 - v1);
double x2 = x * x;
return v1 + (v2 - v0) * x + (v0 - v1 - p) * x2 + p * x2 * x;
}
double CPerlin::SmoothedNoise (int v) {
return Noise (v)/2 + Noise (v-1)/4 + Noise (v+1)/4;
}
int FastFloor (double v) { return (int) ((v < 0) ? v - 1 : v; }
double CPerlin::InterpolatedNoise (double v) {
int i = FastFloor (v);
double v1 = SmoothedNoise (i);
double v2 = SmoothedNoise (i + 1);
#if INTERPOLATION_METHOD == 2
double v0 = SmoothedNoise (i - 1);
double v3 = SmoothedNoise (i + 2);
return CubicInterpolate (v0, v1, v2, v3, v - i);
#elif INTERPOLATION_METHOD == 1
return CosineInterpolate (v1, v2, v - i);
#else
return LinearInterpolate (v1, v2, v - i);
#endif
}
double CPerlin::ComputeNoise (double v) {
double total = 0, amplitude = m_amplitude, frequency = 1.0;
v += m_randomize;
for (int i = 0; i < m_octaves; i++) {
total += InterpolatedNoise (v * frequency) * amplitude;
frequency *= 2.0;
amplitude *= m_persistence;
}
return total;
}
void CPerlin::Setup (double amplitude, double persistence, int octaves, int randomize) {
m_amplitude = (amplitude > 0.0) ? amplitude : 1.0;
m_persistence = (persistence > 0.0) ? persistence : 2.0/3.0;
m_octaves = (octaves > 0) ? octaves : 6;
m_randomize = (randomize < 0) ? (rand() * rand()) & 0xFFFF : randomize;
}
Câu hỏi này rất tuyệt. – sharptooth
http://www.noisemachine.com/talk1/23.html –