Обработка - рендеринг фигур слишком медленный - PullRequest
0 голосов
/ 11 сентября 2018

Я занимался небольшим небольшим проектом с использованием Processing, и эффект, которого я хотел добиться, заключался в формировании и перемещении "гор", используя Perlin Noise с функцией noise (), с 2 параметрами.

Я изначально использовал изображение для фона, но для иллюстрации я сделал фон черным, и это в основном тот же эффект.

Моя проблема в том, что я хочу иметь «историю»горы, потому что они должны исчезнуть через некоторое время, и поэтому я сделал историю PShapes, и нарисовал историю и обновлял ее каждый кадр.

Обновление не проблема, но рисование PShapes, кажется, занимает многовремя снижения частоты кадров с 60 до 10, когда длина истории составляет 100 элементов.

Ниже приведен код, который я использовал:

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);
}

Я пытался использовать различные способы рендеринга "гор": я пытался написать свой собственный класс кривой и рисовать линии, которые связываюточки, но я получаю ту же производительность.Я попытался сгруппировать PShapes в групповой объект PShape, такой как

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

, и у меня была та же производительность.

Я думал об использовании нескольких потоков для визуализации каждой фигуры по отдельности, но после выполнения некоторыхисследования, есть только один поток, который отвечает за рендеринг - поток анимации, так что он тоже мне не поможет.

Я действительно хочу закончить это, это кажется очень простым, но я не могупонять это.

1 Ответ

0 голосов
/ 11 сентября 2018

Одним из возможных решений было бы не рисование всех сгенерированных фигур, а рисование только новой формы.
Конечно, чтобы «увидеть» формы предыдущих кадров, сцену нельзя очистить в начале кадра.
Поскольку сцена никогда не очищается, это может привести к тому, что весь вид будет покрыт фигурами с течением времени. Но если сцена будет слегка затемнена в начале нового кадра, вместо того, чтобы очистить его, то «старые» фигуры со временем станут темнее и темнее. Это дает ощущение, что «старые» кадры со временем уйдут в глубину.

Очистить фон при инициализации:

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

Создание сцены с эффектом затухания:

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);
}

Смотрите превью:

...