Processing - rendering shapes is too slow

孤者浪人 提交于 2020-06-26 14:00:50

问题


I have been doing a small little project using Processing, and the effect I wanted to achieve was a kind of "mountains" forming and moving, using Perlin Noise with the noise() function, with 2 parameters.

I was originally using a image for the background, but for illustrational purposes, I made the background black, and it's basically the same effect.

My issue is that I want to have a "history" of the mountains because they should fade away after some time, and so I made a history of PShapes, and draw the history and update it each frame.

Updating it is no issue, but drawing the PShapes seems to take a lot of time, reducing the frame rate from 60 to 10 when the length of the history is 100 elements.

Below is the code I used :

float noise_y = 0;
float noise_increment = 0.01;

// increment x in the loop by this amount instead of 1
// makes the drawing faster, since the PShapes have less vertices
// however, mountains look sharper, not as smooth
// bigger inc = better fps
final int xInc = 1;

// maximum length of the array
// bigger = less frames :(
final int arrLen = 100;

int lastIndex = 0;

PShape[] history = new PShape[arrLen];
boolean full = false;

// use this to add shapes in the history
PShape aux;

void setup() {
  size(1280, 720);
}

void draw() {
  background(0);

  // create PShape object
  aux = createShape();
  aux.beginShape();
  aux.noFill();
  aux.stroke(255);
  aux.strokeWeight(0.5);

  for (float x = 0; x < width + xInc; x = x + xInc) {
    float noise = noise(x / 150, noise_y) ;
    // get the actual y coordinate
    float y = map(noise, 0, 1, height / 2, 0);
    // create vertex of shape at x, y
    aux.vertex(x, y);
  }
  aux.endShape();
  // push the current one in the history

  history[lastIndex++] = aux;

  // if it reached the maximum length, start it over ( kinda works like a queue )
  if (lastIndex == arrLen) {
    lastIndex = 0;
    full = true;
  }

  // draw the history
  // this part takes the MOST TIME to draw, need to fix it. 
  // without it is running at 60 FPS, with it goes as low as 10 FPS
  if (full) {
    for (int i = 0; i < arrLen; i++) {
      shape(history[i]);
    }
  } else {
    for (int i = 0; i < lastIndex; i++) {
      shape(history[i]);
    }
  }

  noise_y = noise_y - noise_increment;
  println(frameRate);
}

I have tried to use different ways of rendering the "mountains" : I tried writing my own class of a curve and draw lines that link the points, but I get the same performance. I tried grouping the PShapes into a PShape group object like

PShape p = new PShape(GROUP);
p.addChild(someShape);

and I got the same performance.

I was thinking of using multiple threads to render each shape individually, but after doing some research, there's only one thread that is responsible with rendering - the Animation Thread, so that won't do me any good, either.

I really want to finish this, it seems really simple but I can't figure it out.


回答1:


One possible solution would be, not to draw all the generated shapes, but to draw only the new shape.
To "see" the shapes of the previous frames, the scene can't be cleared at the begin of the frame, of course.
Since the scene is never cleared, this would cause, that the entire view is covered, by shapes over time. But if the scene would be slightly faded out at the begin of a new frame, instead of clearing it, then the "older" shapes would get darker and darker by time. This gives a feeling as the "older" frames would drift away into the depth by time.

Clear the background at the initlization:

void setup() {
  size(1280, 720);
  background(0);
}

Create the scene with the fade effect:

void draw() {

    // "fade" the entire view 
    blendMode(DIFFERENCE);
    fill(1, 1, 1, 255);
    rect(0, 0, width, height);

    blendMode(ADD);

    // create PShape object
    aux = createShape();
    aux.beginShape();
    aux.stroke(255);
    aux.strokeWeight(0.5);
    aux.noFill();
    for (float x = 0; x < width + xInc; x = x + xInc) {
      float noise = noise(x / 150, noise_y) ;
      // get the actual y coordinate
      float y = map(noise, 0, 1, height / 2, 0);
      // create vertex of shape at x, y
      aux.vertex(x, y);
    }
    aux.endShape();

    // push the current one in the history
    int currentIndex = lastIndex; 
    history[lastIndex++] = aux;
    if (lastIndex == arrLen)
      lastIndex = 0;

    // draw the newes shape
    shape(history[currentIndex]);

    noise_y = noise_y - noise_increment;
    println(frameRate, full ? arrLen : lastIndex);
}

See the preview:



来源:https://stackoverflow.com/questions/52281399/processing-rendering-shapes-is-too-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!