处理:高效绘制渐变 [英] Processing: efficiently drawing a gradient

查看:40
本文介绍了处理:高效绘制渐变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是处理的新手,我一直致力于模拟电子运动.一切似乎都很好,直到我尝试为每个粒子添加渐变颜色.帧速率大幅下降.

I'm new to Processing and I've been working on simulating electron motion. Everything seems fine until I'm try to add a gradient color to each particle.The frame rate drops considerably.

这是我迄今为止尝试过的:

Here is what I've tried so far:

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

推荐答案

您的问题不是关于模拟电子运动,而是关于在 Processing 中有效地绘制梯度.我看到您已经开始使用示例 > 基础知识 > 颜色 > RadialGradient 示例.请注意,示例本身运行速度很慢,可能是因为关注如何使用颜色 (HSB) 和绘图功能,而不是性能.

Your question isn't about simulating electron motion, but more about efficiently drawing gradients in Processing. I see you've started with the Examples > Basics > Color > RadialGradient sample. Notice that the sample itself runs pretty slow, probably because the focus in on how to use colours (HSB) and drawing functions and less about performance.

您可以做的是使用 PGraphicsPImage,您更喜欢哪个.

What you can do is cache the gradient using PGraphics or PImage, which ever you're more comfortable with.

这是一个使用 PGraphics 的示例,如果您不习惯使用像素,它可能会更简单:

Here's an example using PGraphics, which might be simpler if you're not used to working with pixels:

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,因此可以使用 image() 显示功能与其他 PImage 类似.

It's also worth noting that PGraphics extends PImage, therefore can be displayed using the image() function like and other PImage.

这是使用像素完成的相同缓存概念:

And here's the same caching concept done using pixels:

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() 进行细微调整:

Of course, this would make it easy to use a lot more electrons. Off topic from true electron motion, here are some fun tests by making minor tweaks to 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));
  }
}

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

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

玩得开心!

现在你可以在此处实际运行代码(使用键 1、2、3、4 更改演示):

Now you can actually run the code right here (use keys 1,2,3,4 to change demo):

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>

这篇关于处理:高效绘制渐变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆