I’m currently trying to make an animation using perlin noise. It was too slow so I tried with OpenSimplexNoise and it was better, but still not fast enough.
I’m juste looping through 2D slices of 3D noise in order to create a smooth color changing effect, and I’m doing this on the three rgb channels.
When I put my window in 300x300 it works fine, but beyond 500x500 it becomes laggy.
Is there any way to optimize my code so it isn’t laggy ?
Thanks for your help.
Here’s my code :
float noise_increase = 0.1; // speed of the animation
float definition = 180;
float[] z; // z component that is changing over time for the three rgb channels
OpenSimplexNoise noise;
void setup()
{
size(300, 300);
noise = new OpenSimplexNoise();
z = new float[3];
for(int i = 0; i < 3; i++)
{
z[i] = random(0,1000);
}
}
void draw()
{
drawNoise();
}
void drawNoise()
{
for(int i = 0; i < 3; i++) // increase z component of 3D perlin noise to get the next 2D slice
{
z[i] += noise_increase;
}
for(int x = 0; x < width; x++)
for(int y = 0; y < height; y++)
{
float r = map((float) noise.eval(x / definition, y / definition, z[0]), -1, 1, 0, 255);
float g = map((float) noise.eval(x / definition, y / definition, z[1]), -1, 1, 0, 255);
float b = map((float) noise.eval(x / definition, y / definition, z[2]), -1, 1, 0, 255);
set(x,y,color(r,g,b));
}
}
@kll You told Kazuya_Yoshimisu to use the set function in that other thread which they did here. Why did you change it back now? To me it seems that extra function call would be unnecessary.
Replacing the map function by setting the colorMode appropriately is a good suggestion!
@Kazuya_Yoshimisu Other than that I think you can’t speed it up much unless you want to precompute a large set of noise values
The noise computation itself should be the most costly thing here.
I have recently experimented with noise generated on the gpu via shaders in Unity and that runs a LOT faster, but I have no idea how or if you can do gpu calculations in processing. It’s a whole different level of complexity though.
Ah, yeah, you are right. I think calling your own extra function to write to pixels is the same as using the set(x,y) function though (or worse). I would suggest writing to pixels directly within the for loops. Thanks for the clarification
using set() is the same as using loadPixels() and updatePixels().
But xdef, ydef, colorMode(RGB,2.0) and replacing map() were significant improvements.
Also, using only one noise calculation with colorMode(HSB,255) was a great idea, but that isn’t what I was aiming for.
I think at this point I juste have to give up. When I’m running in 600x600, the time elapsed between each frame is approximatively 130ms and when removing all 3 noises it takes only 10-20ms so the main problem is definitely the noise function.
Still fun to watch it smoothly running in 300x300 though !
Fullscreen, full resolution noise, 3 times per pixel. Yeah, that sounds quite impossible to get running smoothly. Even on high-end hardware and with gpu code.
Depending on what you aim to achieve there are some places you could optimize though.
If you generate noise at half the width and height (quarter the resolution) you can offset the values for each of the layers R G B by one pixel (one layer horizontally and the other vertically). That way perceived loss of resolution is minimal because pixels next to each other still end up having different resulting colors.
You could also (and even in combination with the above) generate your noise at a lower resolution and scale it up. That will show in your result but again, depending on what you’re trying to achieve, you might not need maximum resolution.
If you can get away with a limited set of noise you could pregenerate the noise or the resulting images before showing the animation.
The most acceleration you can achieve in my opinion would be generating the images on the GPU, but like I said, I don’t know if that’s possible in Processing. And even then there are limitations to how much information you can get back from the GPU. Displaying the image on screen is fine, doing more computations back on the CPU won’t be possible.