使用 Processing 在屏幕上烘焙阵列
Baking the arrays on screen with Processing
我喜欢使用 Processing 数组函数,但是当我使用这个函数绘制东西时,我意识到它会将每个绘制的形状存储在内存中,这会导致 CPU 出现峰值。 (尤其是涨到几千的时候)
如何烘焙图形然后删除mouserelease 上的数组对象?我的意思是,Processing 能否在每次笔画后将这些对象视为单个图像,然后我会使用 .remove(0)
函数清除数组?
这是我的代码:
ArrayList <Drawing> drawings = new ArrayList <Drawing>();
void setup() {
size(400, 400);
background(255);
colorMode(HSB);
}
void draw() {
background(255);
for (int i=0;i<drawings.size();i++) {
drawings.get(i).display();
}
println(drawings.size());
}
void mouseDragged() {
drawings.add(new Drawing(mouseX, mouseY));
}
class Drawing {
float x, y, r;
color c;
Drawing(float ax, float ay) {
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
void display() {
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
如果你只想在按下鼠标(绘制新对象)时将对象存储到 ArrayList 中,并且只是让所有旧对象在 ArrayList 的背景上保持静态,你可以这样做:
ArrayList<Drawing> drawings = new ArrayList();
boolean flag = false;
void setup()
{
size(400, 400);
background(255);
colorMode(HSB);
loadPixels();
}
void draw()
{
updatePixels();
if(flag)
{
for(Drawing drawing : drawings)
{
drawing.display();
}
}
println(drawings.size());
}
void mouseDragged()
{
flag = true;
Drawing drawing = new Drawing(mouseX, mouseY);
drawings.add(drawing);
}
void mouseReleased()
{
flag = false;
loadPixels();
drawings = new ArrayList();
}
class Drawing
{
float x, y, r;
color c;
Drawing(float ax, float ay)
{
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
public void display()
{
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
函数 loadPixels() 将屏幕的所有像素存储到 pixels[] 数组中,而 updatePixels() 在 canvas 上绘制 pixels[] 中的像素。这样你就可以在每次释放鼠标时清空你的 ArrayList,即使当 ArrayList 获得数千个元素时你仍然会得到一些 CPU 尖峰,当鼠标没有被拖动或者 ArrayList 少于它减少了数千个元素 CPU 消耗。
如果以后不需要访问绘图对象(比如更改属性),您可以简单地将渲染缓存到单独的 PGraphics layer:
PGraphics drawings;
void setup() {
size(400, 400);
colorMode(HSB);
drawings = createGraphics(width, height);
// use drawing commands between beginDraw() / endDraw() calls
drawings.beginDraw();
drawings.background(255);
drawings.colorMode(HSB);
drawings.noStroke();
drawings.endDraw();
}
void draw() {
background(255);
// PGraphics extends PImage so you can render it the same way
image(drawings, 0, 0);
println((int)frameRate);
}
void mouseDragged() {
drawRandomCircle(drawings, mouseX, mouseY);
}
void drawRandomCircle(PGraphics layer, float x, float y){
float diameter = random(2, 20);
layer.beginDraw();
layer.fill(color(random(100, 200), 255, 255, 88));
layer.ellipse(x, y, diameter, diameter);
layer.endDraw();
}
否则你可以使用PShape:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(addRandomCircle(mouseX, mouseY));
}
PShape addRandomCircle(float x, float y){
float diameter = random(2, 20);
// create an ellipse PShape with the desired dimensions, position, fill and (no)stroke
PShape circle = createShape(ELLIPSE, x, y, diameter, diameter);
circle.setFill(color(random(100, 200), 255, 255, 88));
circle.setStroke(false);
return circle;
}
正如我评论中提到的,查看 Processing > Examples > Demos > Performance > StaticParticlesRetained
如果您以后需要访问每个添加的 circle/drawing 您可以迭代父 PShape:
// iterate though nested PShapes
for(int i = 0 ; i < drawings.getChildCount(); i++){
// access each PShape
PShape drawing = drawings.getChild(i);
// access PShape properties
println("drawings[" + i + "] has " + drawing.getVertexCount() + " vertices");
}
如果您需要额外的功能(例如单独的 属性 来制作动画),您可以随时 extend PShape:重新使用已有的功能,在顶部添加您需要的功能:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// use custom functionality
for(int i = 0 ; i < drawings.getChildCount(); i++){
// cast from PShape superclass to the custom Drawing subclass
Drawing drawing = (Drawing)drawings.getChild(i);
// use the custom functionality
drawing.update(i);
}
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(new Drawing((PGraphicsOpenGL)g, mouseX, mouseY));
}
class Drawing extends PShapeOpenGL{
float x, y, diameter;
Drawing(PGraphicsOpenGL pg, float x, float y){
// call PShape super constructor setting this as a primitive (e.g. POINT, LINE, RECT, ELLIPSE, etc.)
super(pg, PShape.PRIMITIVE);
setKind(ELLIPSE);
diameter = random(2, 20);
// set (ellipse) shape parameters
setParams(new float[]{x, y, diameter, diameter});
// fill
setFill(color(random(100, 200), 255, 255, 88));
// disable stroke
setStroke(false);
// remember original position
this.x = x;
this.y = y;
}
// a custom functionality on top of PShape
void update(int index){
float offset = map(sin((frameCount + ((index+1) * 10)) * 0.025), -1.0, 1.0, -15, 15);
// reset transformations
this.resetMatrix();
// translate backwards
this.translate(-x, -y);
// translate back + the offset
this.translate(x + offset, y);
}
}
有关功能的完整列表,请参阅 PShape javadocs
虽然从最简单的事情开始。如果你想简单地渲染许多形状而不改变它们,PGraphics 可以解决这个问题
我喜欢使用 Processing 数组函数,但是当我使用这个函数绘制东西时,我意识到它会将每个绘制的形状存储在内存中,这会导致 CPU 出现峰值。 (尤其是涨到几千的时候)
如何烘焙图形然后删除mouserelease 上的数组对象?我的意思是,Processing 能否在每次笔画后将这些对象视为单个图像,然后我会使用 .remove(0)
函数清除数组?
这是我的代码:
ArrayList <Drawing> drawings = new ArrayList <Drawing>();
void setup() {
size(400, 400);
background(255);
colorMode(HSB);
}
void draw() {
background(255);
for (int i=0;i<drawings.size();i++) {
drawings.get(i).display();
}
println(drawings.size());
}
void mouseDragged() {
drawings.add(new Drawing(mouseX, mouseY));
}
class Drawing {
float x, y, r;
color c;
Drawing(float ax, float ay) {
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
void display() {
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
如果你只想在按下鼠标(绘制新对象)时将对象存储到 ArrayList 中,并且只是让所有旧对象在 ArrayList 的背景上保持静态,你可以这样做:
ArrayList<Drawing> drawings = new ArrayList();
boolean flag = false;
void setup()
{
size(400, 400);
background(255);
colorMode(HSB);
loadPixels();
}
void draw()
{
updatePixels();
if(flag)
{
for(Drawing drawing : drawings)
{
drawing.display();
}
}
println(drawings.size());
}
void mouseDragged()
{
flag = true;
Drawing drawing = new Drawing(mouseX, mouseY);
drawings.add(drawing);
}
void mouseReleased()
{
flag = false;
loadPixels();
drawings = new ArrayList();
}
class Drawing
{
float x, y, r;
color c;
Drawing(float ax, float ay)
{
x=ax;
y=ay;
r=random(2, 20);
c=color(random(100, 200), 255, 255, 88);
}
public void display()
{
noStroke();
fill(c, 100);
ellipse(x,y, r, r);
}
}
函数 loadPixels() 将屏幕的所有像素存储到 pixels[] 数组中,而 updatePixels() 在 canvas 上绘制 pixels[] 中的像素。这样你就可以在每次释放鼠标时清空你的 ArrayList,即使当 ArrayList 获得数千个元素时你仍然会得到一些 CPU 尖峰,当鼠标没有被拖动或者 ArrayList 少于它减少了数千个元素 CPU 消耗。
如果以后不需要访问绘图对象(比如更改属性),您可以简单地将渲染缓存到单独的 PGraphics layer:
PGraphics drawings;
void setup() {
size(400, 400);
colorMode(HSB);
drawings = createGraphics(width, height);
// use drawing commands between beginDraw() / endDraw() calls
drawings.beginDraw();
drawings.background(255);
drawings.colorMode(HSB);
drawings.noStroke();
drawings.endDraw();
}
void draw() {
background(255);
// PGraphics extends PImage so you can render it the same way
image(drawings, 0, 0);
println((int)frameRate);
}
void mouseDragged() {
drawRandomCircle(drawings, mouseX, mouseY);
}
void drawRandomCircle(PGraphics layer, float x, float y){
float diameter = random(2, 20);
layer.beginDraw();
layer.fill(color(random(100, 200), 255, 255, 88));
layer.ellipse(x, y, diameter, diameter);
layer.endDraw();
}
否则你可以使用PShape:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(addRandomCircle(mouseX, mouseY));
}
PShape addRandomCircle(float x, float y){
float diameter = random(2, 20);
// create an ellipse PShape with the desired dimensions, position, fill and (no)stroke
PShape circle = createShape(ELLIPSE, x, y, diameter, diameter);
circle.setFill(color(random(100, 200), 255, 255, 88));
circle.setStroke(false);
return circle;
}
正如我评论中提到的,查看 Processing > Examples > Demos > Performance > StaticParticlesRetained
如果您以后需要访问每个添加的 circle/drawing 您可以迭代父 PShape:
// iterate though nested PShapes
for(int i = 0 ; i < drawings.getChildCount(); i++){
// access each PShape
PShape drawing = drawings.getChild(i);
// access PShape properties
println("drawings[" + i + "] has " + drawing.getVertexCount() + " vertices");
}
如果您需要额外的功能(例如单独的 属性 来制作动画),您可以随时 extend PShape:重新使用已有的功能,在顶部添加您需要的功能:
PShape drawings;
void setup() {
size(400, 400, P2D);
smooth();
background(255);
colorMode(HSB);
// create a PShape group to append circles to later
drawings = createShape(GROUP);
}
void draw() {
background(255);
// use custom functionality
for(int i = 0 ; i < drawings.getChildCount(); i++){
// cast from PShape superclass to the custom Drawing subclass
Drawing drawing = (Drawing)drawings.getChild(i);
// use the custom functionality
drawing.update(i);
}
// render PShape
shape(drawings);
println(drawings.getChildCount() + " shapes at ~" + (int)frameRate + "fps");
}
void mouseDragged() {
drawings.addChild(new Drawing((PGraphicsOpenGL)g, mouseX, mouseY));
}
class Drawing extends PShapeOpenGL{
float x, y, diameter;
Drawing(PGraphicsOpenGL pg, float x, float y){
// call PShape super constructor setting this as a primitive (e.g. POINT, LINE, RECT, ELLIPSE, etc.)
super(pg, PShape.PRIMITIVE);
setKind(ELLIPSE);
diameter = random(2, 20);
// set (ellipse) shape parameters
setParams(new float[]{x, y, diameter, diameter});
// fill
setFill(color(random(100, 200), 255, 255, 88));
// disable stroke
setStroke(false);
// remember original position
this.x = x;
this.y = y;
}
// a custom functionality on top of PShape
void update(int index){
float offset = map(sin((frameCount + ((index+1) * 10)) * 0.025), -1.0, 1.0, -15, 15);
// reset transformations
this.resetMatrix();
// translate backwards
this.translate(-x, -y);
// translate back + the offset
this.translate(x + offset, y);
}
}
有关功能的完整列表,请参阅 PShape javadocs
虽然从最简单的事情开始。如果你想简单地渲染许多形状而不改变它们,PGraphics 可以解决这个问题