Почему мой алгоритм шума Перлина не смешивается между ячейками сетки?Python

Программы на Python
Ответить
Anonymous
 Почему мой алгоритм шума Перлина не смешивается между ячейками сетки?

Сообщение Anonymous »

Я пытался воспроизвести шум Перлина в Python с помощью модуля Pygame. Я предпринял следующие шаги:
1. Размер окна (1600, 1200). Это окно разделено на сетку из ячеек 40 x 40 пикселей, поэтому сетка разбита на 40 столбцов и 30 строк. Каждая ячейка 40 x 40 далее разбивается на подсетку из подячеек размером 10 x 10 пикселей, поэтому каждая ячейка 40 x 40 имеет 16 подячеек.
2. Углу каждой ячейки присваивается случайный вектор градиента
3. Затем для каждой ячейки сетки подячейки каждой сетки будут зациклены во вложенном цикле for. Для каждой подячейки в ячейке будет рассчитываться вектор смещения между всеми углами ячейки и положением подячейки, а также вычисляться скалярные произведения между ними.
4. Скалярные произведения двух верхних угловых ячеек и двух нижних угловых ячеек затем линейно интерполируются отдельно, давая 2 значения, затем эти значения линейно интерполируются, чтобы получить 1 окончательное значение шума (билинейная интерполяция — использовалась функция Smoothstep)
5. Шаги 3–4 будут выполняться для каждой ячейки сетки и всех подъячеек ячейки, а значениям шума будет присвоено значение в оттенках серого.
Изображение

Проблема в том, что между ячейками цвета по-прежнему случайны, а цвета подячеек между двумя соседними ячейками не случайны. между ними действительно есть большая корреляция/плавное сочетание. Я не слишком уверен, стоит ли просто вставлять сюда часть кода, я вставлю только основные части, но мне было интересно, не сталкивался ли кто-нибудь, кто имел дело с этим алгоритмом, с подобной проблемой.
def CreateGradientVec():
theta = uniform(0, 2 * pi)
gradient_vec = pygame.Vector2(cos(theta), sin(theta))
#Theta chooses a random angle from 0-360 degrees, since sin^2(theta) + cos^2(theta) = 1, so sin(theta) + cos(theta) = 1
#and the gradient vec will be a unit vector in a random resultant direction

return gradient_vec

def SmoothStep(t):
#Formula for smoothstep function
return 3*(t**2) - 2*(t**3)

def BilinearInterpolation(d1, d2, d3, d4, point):
point_normalized = point / CELL_SIZE #NORMALISING CANDIDATE POINT TO BE USED AS INPUT FOR SMOOTHSTEP
#point_normalized *= 0.01
#Bilinear Interpolation Formula
return lerp( lerp(d1, d2, SmoothStep(point_normalized.x)), lerp(d3, d4, SmoothStep(point_normalized.x)), SmoothStep(point_normalized.y))

def PerlinNoise(grid_cells, grid_map):
noise_values = []

for cell in grid_cells:
cell_topleft = cell.GetPos()
cell_noise_values = []
#Finds all 4 corners of a cell, as well as the corresponding gradient vector of each corner
corners = [(Vector2(cell_topleft), grid_map[cell_topleft]),
(Vector2(cell_topleft[0] + CELL_SIZE, cell_topleft[1]), grid_map[(cell_topleft[0] + CELL_SIZE, cell_topleft[1])]),
(Vector2(cell_topleft[0], cell_topleft[1] + CELL_SIZE), grid_map[(cell_topleft[0], cell_topleft[1] + CELL_SIZE)]),
(Vector2(cell_topleft[0] + CELL_SIZE, cell_topleft[1] + CELL_SIZE), grid_map[(cell_topleft[0] + CELL_SIZE, cell_topleft[1] + CELL_SIZE)])
]

for subcell in cell.GetSubCells():
dot_values = []
subcell_pos = Vector2(subcell.GetPos())

for i in range(4):
corner_pos = corners[0]
gradient_vec = corners[1]

offset_vec = (subcell_pos - corner_pos) / CELL_SIZE # Normalises offset vec so both gradient and offset vec are unit vectors

dot_values.append(offset_vec.dot(gradient_vec))

noise_value = BilinearInterpolation(dot_values[0], dot_values[1], dot_values[2], dot_values[3], subcell_pos)

noise_value = (noise_value + 1.5) / 3 #Transforms noise values, so they are not negative and greater than 1

cell_noise_values.append(noise_value)

#Creates a 2D list, where each sub-list contains the noise values for all sub-cells in a single cell
noise_values.append(cell_noise_values)

return noise_values
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»