# Noise generation, aka clouds, is really slow and heavy

Hello there,
I have been working on this small program that I would like to use as a fullscreen background. However, it already is really heavy. Is there a way to fix that in my code or I just have to think of another way to use it?

``````var density = 0.03;
var wind = 0;
var speedOfWind = 0.00002;

function setup() {
canvas = createCanvas(500,500);
//canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0,0);
canvas.style('z-index', -1);
pixelDensity(1);
// frameRate(100);

}

function draw() {

var yoff = 0;
for (var y = 0; y < height; y++) {
var xoff = 0;
for (var x = 0; x < width; x++) {
var index = (x + y * width) * 4;

var r = noise(xoff + wind, yoff - wind) * 255;
pixels[index + 0] = r;
pixels[index + 1] = r;
pixels[index + 2] = r;
pixels[index + 3] = 51;
xoff += density;
}
yoff += density;
wind+= speedOfWind;

}
updatePixels();
}

``````

Just to clarify:
I tried increasing the frameRate() to 100 or 200, but nothing changed.
I am using a MacBook Pro 2014 Retina, so I suppose my resolution is quite high.

Any help would be appreciated. Itâ€™s my first post on the forum. I donâ€™t know if this way of posting code is okay, let me know.

All the best!

Hi! One way to speed it up would be to:

1. copy the image pixels one pixel left and down.
2. generate the top row of pixels using the noise function
3. generate the right column of pixels using the noise function

This way you avoid calling noise for every single pixel on the screen, but only a tiny fraction of them.

Another (more complex, faster) option is to use shaders to generate that background.

2 Likes

To add to @hamoid answer, the `frameRate` function is not working the way you think.

Calling `frameRate(100)` wonâ€™t make your sketch faster. It is just a limit speed that you are setting. It means that no matter how fast you can generate the next image, you wonâ€™t display it unless 10 milliseconds has passed since the last image, insuring that you wonâ€™t have more than 100 frame generated in 1 second.

1 Like

Good point @jb4x, I forgot to mention that

Minor correction (typo?): for frameRate(100) itâ€™s â€ś10ms has passedâ€ť instead of â€ś100ms has passedâ€ť.(1000ms/100frames=10ms/frame and the default is 1000ms/60frames=16.666ms/frame).

Thanks, itâ€™s corrected

Hello, thank you for your quick reply. I tried to figure this out but I couldnâ€™t.
I got the copy() function, but I cannot implement it. In the example, an image is copied, how do I copy the pixels? I am very confusedâ€¦

I am posting another version of the sketch here, if you would like to give me an example
https://editor.p5js.org/michelangelo/sketches/Hkehv3bJE

Hi! I know itâ€™s not very intuitive to copy an image onto itself
Here something you could use to get started

https://editor.p5js.org/abe/sketches/HkQBn3WJE

Hi,
something weird happened yesterday, because my post was flagged for spam!?!

Anyway, yesterday I made this https://editor.p5js.org/michelangelo/sketches/Hkehv3bJE.
Your example really helped! Thank you!

Now there are still a few problems:
â€“ The generated image is a bit skewed, I donâ€™t understand why, is it the speed of the draw(), is it something else.
â€“ The way I make the initial image in the setup() and later in draw(), seems a bit redundant, but I canâ€™t think of a better way.
â€“ Maybe my if statement is also not proper?
â€“ Aaaand at the end, is the sketch faster? How can I test that: is the Performance tab from the Dev tools for this kind of a test.

Thank you again

â€“ The generated image is a bit skewed, I donâ€™t understand why, is it the speed of the draw(), is it something else.

You need to offset the noise to counteract the movement. Even if you always calculate the noise for the same positions (top and right borders), you should add an â€śimaginaryâ€ť offset because you are actually sampling noise from a position that goes up and right.

In code, an alternative that would work is this:

``````var r = noise((x+frameCount)*density,
(y-frameCount)*density) * 255;
``````

Notice how there is a variable that always increases (frameCount). You donâ€™t need to use x, y and frameCount, but this was the easiest working approach I could think of.

â€“ The way I make the initial image in the setup() and later in draw(), seems a bit redundant, but I canâ€™t think of a better way.

To avoid redundancy, you could create a function like this:

``````function setPixel(image, pixelIndex, colorValue);
``````

and you could call this function in both places (in setup and in draw), so you avoid repeating code.

â€“ Maybe my if statement is also not proper?

Itâ€™s not efficient Itâ€™s better to make two non-nested for loops. The first for loop iterates over 500 pixels. The second for loop can iterate over 499 pixels (if you do 500 pixels you repeat the corner pixel). Thatâ€™s a total of 999 iterations. Instead, if you nest the two for loops you are doing 500x500 iterations (250.000) and on top of that thereâ€™s an if-statement to skip 249.001 of those iterations. If you have two for loops one after the other you donâ€™t need the if statement, and you iterate much less.

â€“ Aaaand at the end, is the sketch faster? How can I test that: is the Performance tab from the Dev tools for this kind of a test.

You could use the Dev tools, or a very simple approach: add this at the end of draw:

``````if(frameCount % 60 == 0) { console.log(floor(frameRate())); }
``````

which will print the frame rate every second. Of course this is only useful if you are hitting the frame rate limit (say it used to be 30 with the previous approach, and now itâ€™s 50). If you were at 60 fps already then maybe you didnâ€™t need to optimize it

Thank you for your help! I understand my mistakes. Super nice that you gave me some examples.

Wish you all the best

1 Like