1

私はProcessingを初めて使用し、電子の動きのシミュレーションに取り組んできました。各パーティクルにグラデーションカラーを追加しようとするまでは、すべて問題ないようです。フレームレートは大幅に低下します。

これが私がこれまでに試したことです:

float a=0;
float s;
void setup()
{
  size(500,500);
  smooth();
  frameRate(500);
  colorMode(HSB,360,100,100);
  noStroke();
  ellipseMode(RADIUS);
}

void draw()
{
  background(200,0,100);
  pushMatrix();
  translate(width/2, height/2);
  rotate(radians(-18));
  for ( int r = width ; r >= 0; r = r - 1 )
  {
    s = 500*exp(-r);
    fill(202, s, 100);
    ellipse(100*cos(a), 50*sin(a), r, r);

  }
  a+=0.1;
  popMatrix();
}
4

1 に答える 1

11

あなたの質問は、電子の動きをシミュレートすることではなく、処理で効率的にグラデーションを描くことについてです。例>基本>色>RadialGradientサンプルから始めたようです。サンプル自体の実行がかなり遅いことに注意してください。おそらく、色(HSB)と描画関数の使用方法に焦点が当てられており、パフォーマンスには焦点が当てられていないためです。

できることは、PGraphicsまたはPImageのどちらか使いやすい方を使用してグラデーションをキャッシュすることです。

PGraphicsを使用した例を次に示します。これは、ピクセルの操作に慣れていない場合は簡単かもしれません。

PImage e;
void setup(){
  size(500,500);
  e = getElectronImg(30,30,0,100,100);//create a cached drawing
}
void draw(){
  background(255);
  translate(width * .5, height * .5);
  float a = frameCount * .1;
  image(e,100*cos(a), 50*sin(a));
}

PImage getElectronImg(int w,int h,int hue,int satMax,int brightness){
  PGraphics electron = createGraphics(w+1,h+1);//create a PGraphics object
  electron.beginDraw();//init drawing using the same Processing drawing functions
    electron.colorMode(HSB,360,100,100);
    electron.background(0,0);//transparent bg
    electron.noStroke();
    int cx = electron.width/2;
    int cy = electron.height/2;
    for (int r = w; r > 0; --r) {
      electron.fill(hue,map(r,0,w,satMax,0),brightness);
      electron.ellipse(cx, cy, r, r);
    }
  electron.endDraw();
  return electron;
}

PGraphicsはPImageを拡張するため、他のPImageと同様にimage()関数を使用して表示できることにも注意してください。

そして、ピクセルを使用して行われるのと同じキャッシュの概念があります。

PImage e;
void setup(){
  size(500,500);
  e = getElectronImg(30,30,0,100,100);
}
void draw(){
  background(255);
  translate(width * .5, height * .5);
  float a = frameCount * .1;
  image(e,100*cos(a), 50*sin(a));
}

PImage getElectronImg(int w,int h,int hue,int satMax,int brightness){
  pushStyle();//isolate drawing styles such as color Mode
    colorMode(HSB,360,100,100);
    PImage electron = createImage(w,h,ARGB);//create an image with an alpha channel
    int np = w * h;//total number of pixels
    int cx = electron.width/2;//center on x
    int cy = electron.height/2;//center on y
    for(int i = 0 ; i < np; i++){//for each pixel
      int x = i%electron.width;//compute x from pixel index
      int y = (int)(i/electron.width);//compute y from pixel index
      float d = dist(x,y,cx,cy);//compute distance from centre to current pixel
      electron.pixels[i] = color(hue,map(d,0,cx,satMax,0),brightness,map(d,0,cx,255,0));//map the saturation and transparency based on the distance to centre
    } 
    electron.updatePixels();//finally update all the pixels
  popStyle();
  return electron;
}

もちろん、これにより、より多くの電子を簡単に使用できるようになります。真の電子運動から離れたトピックですが、draw()に微調整を加えることによるいくつかの楽しいテストがあります。

void draw(){
  background(255);
  translate(width * .5, height * .5);
  for(int i = 0 ; i < 200 ; i++){
    float a = (frameCount * .025 + (i*.1));
    image(e,(100+i)*cos(a + i), (50+i)*sin(a + i));
  }
}

200

void draw(){
  background(255);
  translate(width * .5, height * .5);
  for(int i = 0 ; i < 1000 ; i++){
    float a = (frameCount * .025 + (i*.1));
    image(e,(100+(i * .25))*cos(a + i), (50+(i * .25))*sin(a + i));
  }
}

1000

void draw(){
  background(255);
  translate(width * .5, height * .5);
  scale(.25);
  for(int i = 0 ; i < 5000 ; i++){
    float a = (frameCount * .025 + (i*.1));
    image(e,sin(a) * (100+(i * .5))*cos(a + i),  (50+(i * .25))*sin(a + i));
  }
}

5K

楽しむ!

これで、実際にここでコードを実行できます(デモを変更するには、キー1、2、3、4を使用します)。

var e,demo = 2;
function setup(){
  createCanvas(500,500);
  e = getGradientImg(30,30,0,100,100);
}
function draw(){
  background(255);
  translate(width * .5, height * .5);
  if(demo == 1){
    var a = frameCount * .1;
    image(e,100*cos(a), 50*sin(a));
  }
  if(demo == 2){
    for(var i = 0 ; i < 200 ; i++){
      var a = (frameCount * .025 + (i*.1));
      image(e,(100+i)*cos(a + i), (50+i)*sin(a + i));
    }
  }
  if(demo == 3){
    for(var i = 0 ; i < 1000 ; i++){
      var a = (frameCount * .025 + (i*.1));
      image(e,(100+(i * .25))*cos(a + i), (50+(i * .25))*sin(a + i));
    }
  }
  if(demo == 4){
    scale(.2);
    for(var i = 0 ; i < 5000 ; i++){
      var a = (frameCount * .025 + (i*.1));
      image(e,sin(a) * (100+(i * .5))*cos(a + i),  (50+(i * .25))*sin(a + i));
    }
  }
}
function keyReleased(){
  if(key === '1') demo = 1;
  if(key === '2') demo = 2;
  if(key === '3') demo = 3;
  if(key === '4') demo = 4;
}

function getGradientImg(w,h,hue,satMax,brightness){
  push();//isolate drawing styles such as color Mode
    colorMode(HSB,360,100,100);
    var gradient = createImage(w,h);//create an image with an alpha channel
    var np = w * h;//total number of pixels
    var np4 = np*4;
    var cx = floor(gradient.width * 0.5);//center on x
    var cy = floor(gradient.height * 0.5);//center on y
    gradient.loadPixels();
    for(var i = 0 ; i < np4; i+=4){//for each pixel
      var id4 = floor(i * .25);
      var x = id4%gradient.width;//compute x from pixel index
      var y = floor(id4/gradient.width);//compute y from pixel index
      var d = dist(x,y,cx,cy);//compute distance from centre to current pixel
      //map the saturation and transparency based on the distance to centre
      gradient.pixels[i]   = hue;
      gradient.pixels[i+1] = map(d,0,cx,satMax,0);
      gradient.pixels[i+2] = brightness;
      gradient.pixels[i+3] = map(d,0,cx,255,0);
    }
    gradient.updatePixels();//finally update all the pixels
  pop();
  return gradient;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

于 2012-12-09T14:01:37.983 に答える