我正在制作一个程序,以测试我对Perlin噪声产生算法的尝试。 Perlin噪声本身似乎很好,但是我发现在画布上绘制噪音非常慢。这可能是因为在画布中的每个点上,我必须调用stroke()函数以更改下一个像素的颜色,然后绘制该像素。这是在400*400个像素帆布上完成的,因此我正在用中风()160,000次更改颜色,并调用点()160,000次。
这需要一些时间才能做。我想知道是否有任何方法可以更快。也许如果我可以将Perlin噪声转换为图像,那么加载该图像而不是单独绘制所有160,000点?
我的绘制循环的代码在下面
function draw() {
background(220);
strokeWeight(1);
for(var row = 0; row < height; row ++)
{
for(var column = 0; column < width; column ++)
{
//takes a noise value from the myNoise array whose elements have a range of [-1,1] and turns it into a value from [0,256], and makes that the color of the next point
stroke((myNoise[row][column]+1)*128);
point(column,row)
}
}
noLoop();
}
:我使用以下代码创建和加载图像。归功于Samathingamajig的小费。
function draw() {
background(220);
img = createImage(width,height);
img.loadPixels();
for(var row = 0; row < height; row ++)
{
for(var column = 0; column < width; column ++)
{
//takes a noise value from the myNoise array whose elements have a range of [-1,1] and turns it into a value from [0,256], and makes that the color of the next pixel in the image
img.set(row,column,color((myNoise[row][column]+1)*128))
}
}
img.updatePixels();
image(img,0,0)
noLoop();
}
Samathingamajig还指出,我已经更改了400*400是160,000,而不是1,600。
我的原始代码花了大约4秒钟来运行拉动循环。这个新版本大约需要0.75秒。
我还按照Rednoyz建议使用createGraphics()方法进行了测试。这不像使用图像方法那样快,因为它仍然需要我调用stroke()160,000次。
这两种解决方案都为我提供了一个可以很快绘制的图像,但是CreateImage()允许我在比CreateGraphics()()的时间更少的时间内创建图像。
I am making a program to test out my attempt at a Perlin Noise generating algorithm. The Perlin noise itself seems fine, however I've found that drawing that noise on the canvas is very slow. This is probably because for every single point in the canvas I have to call the stroke() function to change the color of the next pixel, then draw that pixel. This is done over a 400*400 pixel canvas, so I am changing the color with stroke() 160,000 times and calling point() 160,000 times.
This takes some time to do. I was wondering if there is any way of making this faster. Perhaps if I could turn the Perlin noise into an image, then load that image instead of drawing all 160,000 points individually?
The code of my draw loop is below
function draw() {
background(220);
strokeWeight(1);
for(var row = 0; row < height; row ++)
{
for(var column = 0; column < width; column ++)
{
//takes a noise value from the myNoise array whose elements have a range of [-1,1] and turns it into a value from [0,256], and makes that the color of the next point
stroke((myNoise[row][column]+1)*128);
point(column,row)
}
}
noLoop();
}
Edit: I used the following code to create and load an image. Credit to Samathingamajig for the tip.
function draw() {
background(220);
img = createImage(width,height);
img.loadPixels();
for(var row = 0; row < height; row ++)
{
for(var column = 0; column < width; column ++)
{
//takes a noise value from the myNoise array whose elements have a range of [-1,1] and turns it into a value from [0,256], and makes that the color of the next pixel in the image
img.set(row,column,color((myNoise[row][column]+1)*128))
}
}
img.updatePixels();
image(img,0,0)
noLoop();
}
Also Samathingamajig pointed out that 400*400 is 160,000, not 1,600, which I have changed above.
My original code took about 4 seconds to run the draw loop. This new version takes about 0.75 seconds.
I also tested using the createGraphics() method as suggested by rednoyz. This was not as fast as using the image methods because it still requires me to call stroke() 160,000 times.
Both of these solutions gave me an image that I could very quickly draw, however createImage() allowed me to create the image in much less time than createGraphics() did.
发布评论
评论(2)
只是为了对现有建议添加一点细微差别:
使用
pixels []
而不是set> set> set(x,y,color)>
:想到一个1D索引,该索引考虑了[R,G,B,A,...] Pixels Order,并且(
pixeldentess
in tablees),但它更快。文档提到:
就您的情况而言,看起来大致如下:(
也循环一次而不是嵌套环会有所帮助)。
关于
point()
,它可能会使用beginshape(point); vertex(x,y); endShape();
show幕后的东西,这意味着这样的东西是效率稍高:也就是说,它可能无法按预期工作:
beginshape()/endShape()
呈现这一顶点可能仍然非常慢,尽管一个更高级的主题,但应该快速的另一个选项是
shader()
。 (可能会在Shadertoy.com上找到一些Perlin噪音灵感)。P5.JS很棒,但主要目标是没有表现最多的画布渲染器。如果此阶段着色器有点太复杂了,但是您一般对JavaScript感到满意,您可以查看其他库,例如(也许 pixi粒子 - emitter 可以很方便吗?)
Just to add a bit of nuance to the existing suggestion:
use
pixels[]
instead ofset(x, y, color)
: it's less intuitive to think of a 1D index that takes into account [r,g,b,a,...] pixels order, and (pixelDensity
on retina displays), but it is faster.The documentation mentions:
In your case that would roughly look like this:
(also looping once instead of nested looping will help).
Regarding
point()
, it might use something likebeginShape(POINTS);vertex(x,y);endShape();
behind the scenes which means something like this would be slightly more efficient:That being said, it might not work as intended:
beginShape()/endShape()
Although a more advanced topic, another option that should be fast is
shader()
. (Might find some perlin noise inspiration on shadertoy.com btw).p5.js is great to learn with but it's main goal is not to have the most performant canvas renderers. If shaders are a bit too complex at this stage, but you're comfortable with javascript in general, you can look at other libraries such as pixi.js (maybe pixi particle-emitter could be handy ?)
我已经尝试了很多毫秒测试,并且图像方法是迄今为止最好的。当您指出的那样,问题实际上只是您试图处理的像素数量。
测试: https://editor.p5js.s.org/koderm/koderm/koderm/skethes/sketches/6xpirw_98s
I've tried a lot of millisecond tests, and the image approach is by FAR the best. The problem is really just the amount of pixels you're trying to process as @Samathinamajig pointed out.
testing: https://editor.p5js.org/KoderM/sketches/6XPirw_98s