patterncsharpMinor
Is there a way to optimise my Perlin noise?
Viewed 0 times
perlinwayoptimisenoisethere
Problem
I just started using Perlin noise a few days ago, and the results look quite good. But it takes over 3 seconds to calculate and draw a 1024x1024 bitmap of said noise. I use an array of 1024x1024 to store
Please note that the variable
```
private void button1_Click(object sender, EventArgs e)
{
sw.Start();
LibNoise.Perlin perlinMap = new LibNoise.Perlin();
perlinMap.Lacunarity = lacunarity + 0.01d;
perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;
perlinMap.OctaveCount = octaveCount;
perlinMap.Persistence = persistence;
perlinMap.Frequency = frequency;
perlinMap.Seed = 1024;
if (radioButton1.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.Low;
else if (radioButton2.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.Standard;
else if (radioButton3.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;
double sample = trackBar6.Value * 10;
double[,] perlinArray = new double[resolutieX, resolutieY];
for (int x = 0; x < resolutieX; x++)
{
for (int y = 0; y < resolutieY; y++)
{
perlinArray[x, y] = perlinMap.GetValue(x / sample, y / sample, 1d);
}
}
draw(perlinArray);
textBox12.Text = sw.ElapsedMilliseconds.ToString() + "ms";
sw.Reset();
}
public void draw(double[,] array)
{
Bitmap afbeelding = new Bitmap(1024, 1024);
Color color;
int tileSize = 1024 / resolutieY;
for (int y = 1; y < resolutieY; y++)
{
for (int x = 1; x < resolutieX; x++)
{
if (array[x, y] <= -0.2)
color = Color.DarkBlue;
if (array[x, y] <= 0)
color = Color.DarkBlue;
int32s ranging from -1 to 1.Please note that the variable
tileSize equals 1024 / resolutieX. This is in case I want to use a lower resolution Perlin noise.```
private void button1_Click(object sender, EventArgs e)
{
sw.Start();
LibNoise.Perlin perlinMap = new LibNoise.Perlin();
perlinMap.Lacunarity = lacunarity + 0.01d;
perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;
perlinMap.OctaveCount = octaveCount;
perlinMap.Persistence = persistence;
perlinMap.Frequency = frequency;
perlinMap.Seed = 1024;
if (radioButton1.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.Low;
else if (radioButton2.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.Standard;
else if (radioButton3.Checked)
perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;
double sample = trackBar6.Value * 10;
double[,] perlinArray = new double[resolutieX, resolutieY];
for (int x = 0; x < resolutieX; x++)
{
for (int y = 0; y < resolutieY; y++)
{
perlinArray[x, y] = perlinMap.GetValue(x / sample, y / sample, 1d);
}
}
draw(perlinArray);
textBox12.Text = sw.ElapsedMilliseconds.ToString() + "ms";
sw.Reset();
}
public void draw(double[,] array)
{
Bitmap afbeelding = new Bitmap(1024, 1024);
Color color;
int tileSize = 1024 / resolutieY;
for (int y = 1; y < resolutieY; y++)
{
for (int x = 1; x < resolutieX; x++)
{
if (array[x, y] <= -0.2)
color = Color.DarkBlue;
if (array[x, y] <= 0)
color = Color.DarkBlue;
Solution
Your check
serves no purpose, if your number is indeed lessthan or equal -.2 then it will also hit the next check if it is lessthan or equal to 0.
A prettier way to write if-else blocks like yours would have been to use the ternary operator...
Your method
Your worst case scenario for the
If you structured those in binary search design, ie. start from the middle and eliminate half of the spectrum at a time and work your way out, worst case scenario is that you have to hit half of your IFs. The code for this may look ugly, but it would help.
The most inefficient thing about your code though, and the reason it is taking so long to process is most likely your quadruple nested
I would recommend instead, to create the 2d array of colors in that first double
If possible, instead just create a max resolution version of your image, and rely on the
if (array[x, y] <= -0.2)
color = Color.DarkBlue;serves no purpose, if your number is indeed lessthan or equal -.2 then it will also hit the next check if it is lessthan or equal to 0.
A prettier way to write if-else blocks like yours would have been to use the ternary operator...
color = array[x, y] <= 0.0 ? Color.DarkBlue :
array[x, y] <= 0.1 ? Color.Blue :
array[x, y] <= 0.2 ? Color.Beige :
array[x, y] <= 0.22 ? Color.LightGreen :
array[x, y] <= 0.40 ? Color.Green :
array[x, y] <= 0.75 ? Color.DarkGreen :
array[x, y] <= 0.8 ? Color.LightSlateGray :
array[x, y] <= 0.9 ? Color.Gray :
array[x, y] <= 1.0 ? Color.DarkSlateGray :
Color.DarkSlateGray ;Your method
draw is a public method, and should be PascalCase not camelCaseYour worst case scenario for the
if-else chain is that you have to hit every single one of those IFs. If you structured those in binary search design, ie. start from the middle and eliminate half of the spectrum at a time and work your way out, worst case scenario is that you have to hit half of your IFs. The code for this may look ugly, but it would help.
The most inefficient thing about your code though, and the reason it is taking so long to process is most likely your quadruple nested
for-loopfor (int y = 1; y < resolutieY; y++)
{
for (int x = 1; x < resolutieX; x++)
{
//color calculations
for (int i = 0; i < tileSize; i++)
{
for (int j = 0; j < tileSize; j++)
{
afbeelding.SetPixel(((x - 1) * tileSize) + i, ((y - 1) * tileSize) + j, color);
}
}
}
}I would recommend instead, to create the 2d array of colors in that first double
for-loop, then, loop over that Color[,] and set the pixels. If possible, instead just create a max resolution version of your image, and rely on the
PictureBox's ability to scale the image for you.Code Snippets
if (array[x, y] <= -0.2)
color = Color.DarkBlue;color = array[x, y] <= 0.0 ? Color.DarkBlue :
array[x, y] <= 0.1 ? Color.Blue :
array[x, y] <= 0.2 ? Color.Beige :
array[x, y] <= 0.22 ? Color.LightGreen :
array[x, y] <= 0.40 ? Color.Green :
array[x, y] <= 0.75 ? Color.DarkGreen :
array[x, y] <= 0.8 ? Color.LightSlateGray :
array[x, y] <= 0.9 ? Color.Gray :
array[x, y] <= 1.0 ? Color.DarkSlateGray :
Color.DarkSlateGray ;for (int y = 1; y < resolutieY; y++)
{
for (int x = 1; x < resolutieX; x++)
{
//color calculations
for (int i = 0; i < tileSize; i++)
{
for (int j = 0; j < tileSize; j++)
{
afbeelding.SetPixel(((x - 1) * tileSize) + i, ((y - 1) * tileSize) + j, color);
}
}
}
}Context
StackExchange Code Review Q#54065, answer score: 6
Revisions (0)
No revisions yet.