Что не так с моим генератором шума C# Perlin?C#

Место общения программистов C#
Ответить
Anonymous
 Что не так с моим генератором шума C# Perlin?

Сообщение Anonymous »

Я пытался написать собственную реализацию алгоритма шума Перлина на основе этой статьи. Однако в конечном итоге получается странный шаблон, который довольно далек от того результата, который я искал.
Вот мой код:

Код: Выделить всё

using System;
using System.Drawing;

class PerlinNoise2D
{
// Fade function for smoothing transitions
private static double Fade(double t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}

// Linear interpolation function
private static double Lerp(double t, double a, double b)
{
return a + t * (b - a);
}

// Dot product of gradient and displacement vectors
private static double DotGridGradient(int gridX, int gridY, double x, double y, Random rand)
{
// Generate a pseudo-random gradient vector at the grid point
double angle = rand.NextDouble() * Math.PI * 2;
double gradX = Math.Cos(angle);
double gradY = Math.Sin(angle);

// Displacement vector from grid point to input point
double dx = x - gridX;
double dy = y - gridY;

// Return dot product
return (dx * gradX + dy * gradY);
}

// Noise function for a single layer
public static double Noise(double x, double y, int gridSize, Random rand)
{
// Identify the grid cell the point is in
int x0 = (int)Math.Floor(x) % gridSize;
int y0 = (int)Math.Floor(y) % gridSize;
int x1 = (x0 + 1) % gridSize;
int y1 = (y0 + 1) % gridSize;

// Local coordinates within the grid cell
double localX = x - Math.Floor(x);
double localY = y - Math.Floor(y);

// Apply fade function to smooth transitions
double xFade = Fade(localX);
double yFade = Fade(localY);

// Compute dot products with gradients at each corner
double n00 = DotGridGradient(x0, y0, x, y, rand);
double n10 = DotGridGradient(x1, y0, x, y, rand);
double n01 = DotGridGradient(x0, y1, x, y, rand);
double n11 = DotGridGradient(x1, y1, x, y, rand);

// Interpolate along x for the two rows
double nx0 = Lerp(xFade, n00, n10);
double nx1 = Lerp(xFade, n01, n11);

// Interpolate along y for the final noise value
return Lerp(yFade, nx0, nx1);
}

// Perlin noise with multiple octaves for fractal-like detail
public static double Perlin(double x, double y, int gridSize, int octaves, double persistence)
{
double total = 0;
double frequency = 1;
double amplitude = 1;
double maxValue = 0;

// Random seed for consistent results (same noise pattern for the same inputs)
Random rand = new(69);

// Iterates through octaves (layers of noise)
for (int i = 0; i < octaves; i++)
{
// Generates noise for current octave (scaled by frequency and amplitude)
total += Noise(x * frequency, y * frequency, gridSize, rand) * amplitude;

// Amplitude added to max possible value
maxValue += amplitude;

// Persistence is a factor between 0 and 1, which dictates how much each successive octave contributes
amplitude *= persistence;

// Frequency is doubled as higher octaves have smaller frequencies
frequency *= 2;
}

// Returns noise normalized to a [0, 1] range
return total / maxValue;
}

static void Main()
{
// Configuration for the Perlin noise
int width = 512;           // Width of the output image
int height = 512;          // Height of the output image
int gridSize = 16;         // Size of the grid for noise
int octaves = 4;           // Number of noise octaves
double persistence = 0.5;  // Persistence factor

// Create a bitmap to store the Perlin noise
Bitmap bitmap = new Bitmap(width, height);

// Generate Perlin noise for each pixel
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width;  x++)
{
// Normalize coordinates for Perlin noise
double noiseX = (double)x / width * gridSize;
double noiseY = (double)y / height * gridSize;

// Compute Perlin noise value using the provided implementation
double noiseValue = Perlin(noiseX, noiseY, gridSize, octaves, persistence);

// Map noise value to grayscale (0-255)
int gray = (int)(noiseValue * 255);
gray = Math.Max(0, Math.Min(255, gray)); // Ensure it's within valid range

Color color = Color.FromArgb(gray, gray, gray);

// Set the pixel color in the bitmap
bitmap.SetPixel(x, y, color);
}
}

// Save the image to a file
bitmap.Save("PerlinNoise.png");
Console.WriteLine("Perlin noise image saved as 'PerlinNoise.png'.");
}
}
И созданное изображение выглядит так:
[img]https://i.sstatic.net /trRr45ny.png[/img]

Я пробовал возиться с функцией шума и функцией скалярного произведения, но не уверен, что на самом деле происходит не так. Я подозреваю, что допустил глупую ошибку в логике, поэтому, если бы кто-нибудь из вас указал мне на это, я был бы очень признателен.

Подробнее здесь: https://stackoverflow.com/questions/791 ... -generator
Ответить

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

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

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

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

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