处理 - 渲染形状太慢
Processing - rendering shapes is too slow
我一直在使用 Processing 做一个小项目,我想要实现的效果是一种 "mountains" 形成和移动,使用 Perlin Noise 和 noise() 函数,有 2 个参数。
我本来是用图片做背景的,为了图解,我把背景调成了黑色,效果基本一样。
我的问题是我想要一个 "history" 的山脉,因为它们应该在一段时间后消失,所以我制作了 PShapes 的历史,绘制历史并在每一帧更新它。
更新没问题,但是绘制PShapes好像要花很多时间,当历史长度为100个元素时,帧率从60降到10。
下面是我使用的代码:
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);
}
我尝试使用不同的方式来渲染 "mountains" :我尝试编写自己的 class 曲线并绘制 link 点的线,但我得到了相同的性能。我尝试将 PShape 分组到一个 PShape 组对象中,例如
PShape p = new PShape(GROUP);
p.addChild(someShape);
我得到了同样的表现。
我曾考虑使用多个线程来单独渲染每个形状,但经过一番研究,只有一个线程负责渲染 - 动画线程,所以这对我也没有任何好处。
我真的很想完成这个,看起来很简单,但我想不通。
一种可能的解决方案是,不绘制所有生成的形状,而是只绘制新形状。
对于"see"前几帧的形状,当然无法在帧的开头清除场景。
由于场景永远不会被清除,这将导致整个视图随着时间的推移被形状覆盖。但是如果场景在新帧开始时稍微淡出,而不是清除它,那么 "older" 形状会随着时间变得越来越暗。这给人的感觉是 "older" 帧会随着时间的推移逐渐消失。
初始化时清除背景:
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);
}
查看预览:
我一直在使用 Processing 做一个小项目,我想要实现的效果是一种 "mountains" 形成和移动,使用 Perlin Noise 和 noise() 函数,有 2 个参数。
我本来是用图片做背景的,为了图解,我把背景调成了黑色,效果基本一样。
我的问题是我想要一个 "history" 的山脉,因为它们应该在一段时间后消失,所以我制作了 PShapes 的历史,绘制历史并在每一帧更新它。
更新没问题,但是绘制PShapes好像要花很多时间,当历史长度为100个元素时,帧率从60降到10。
下面是我使用的代码:
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);
}
我尝试使用不同的方式来渲染 "mountains" :我尝试编写自己的 class 曲线并绘制 link 点的线,但我得到了相同的性能。我尝试将 PShape 分组到一个 PShape 组对象中,例如
PShape p = new PShape(GROUP);
p.addChild(someShape);
我得到了同样的表现。
我曾考虑使用多个线程来单独渲染每个形状,但经过一番研究,只有一个线程负责渲染 - 动画线程,所以这对我也没有任何好处。
我真的很想完成这个,看起来很简单,但我想不通。
一种可能的解决方案是,不绘制所有生成的形状,而是只绘制新形状。
对于"see"前几帧的形状,当然无法在帧的开头清除场景。
由于场景永远不会被清除,这将导致整个视图随着时间的推移被形状覆盖。但是如果场景在新帧开始时稍微淡出,而不是清除它,那么 "older" 形状会随着时间变得越来越暗。这给人的感觉是 "older" 帧会随着时间的推移逐渐消失。
初始化时清除背景:
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);
}
查看预览: