处理3改进密集型数学计算 [英] Processing 3 improving intensive math calculation

查看:106
本文介绍了处理3改进密集型数学计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个非常简单的草图来模拟两个平面波的干涉,非常容易.

I wrote a very simple sketch to simulate the interference of two planar waves, very easy.

对于CPU来说,这个问题似乎有点复杂(而且处理仅使用一个内核),而我只能获得1 o 2 fps.

The problem seems to be a little to much intensive for the cpu (moreover processing uses only one core) and I get only 1 o 2 fps.

有什么想法可以改善这个草图吗?

Any idea how to improve this sketch?

float x0;
float y0;
float x1;
float y1;
float x2;
float y2;
int t = 0;

void setup() {
  //noLoop();
  frameRate(30);
  size(400, 400, P2D);
  x0 = width/2;
  y0 = height/2;
  x1 = width/4;
  y1 = height/2;
  x2 = width * 3/4;
  y2 = height / 2;
}

  void draw() {
  background(0);

  for (int x = 0; x <= width; x++) {
    for (int y = 0; y <= height; y++) {

      float d1 = dist(x1, y1, x, y);
      float d2 = dist(x2, y2, x, y);
      float factorA = 20;
      float factorB = 80;
      float wave1 = (1 + (sin(TWO_PI * d1/factorA + t)))/2 * exp(-d1/factorB);
      float wave2 = (1 + (sin(TWO_PI * d2/factorA + t)))/2 * exp(-d2/factorB);
      stroke( (wave1 + wave2) *255);
      point(x, y);
    }
  }

  t--; //Wave propagation
  //saveFrame("wave-##.png");
}

推荐答案

正如凯文(Kevin)所建议的那样,使用point()并不是最有效的方法,因为它会调用beginShape();vertex() and endShape();.使用像素可能会更好.

As Kevin suggested, using point() isn't the most efficient method since it calls beginShape();vertex() and endShape();. You might be off better using pixels.

此外,嵌套循环可以写为单个循环,并且可以避免dist()在后台使用平方根的情况(可以使用具有更大值的平方距离).

Additionally, the nested loops can be written as a single loop and dist() which uses square root behind the scenes can be avoided (you can uses squared distance with higher values).

以下是使用这些版本的版本:

Here's a version using these:

float x1;
float y1;
float x2;
float y2;
int t = 0;
//using larger factors to use squared distance bellow instead of dist(),sqrt()
float factorA = 20*200;
float factorB = 80*200;

void setup() {
  //noLoop();
  frameRate(30);
  size(400, 400);
  x1 = width/4;
  y1 = height/2;
  x2 = width * 3/4;
  y2 = height / 2;
  //use pixels, not points()
  loadPixels();
}

void draw() {
  for (int i = 0; i < pixels.length; i++) {
    int x = i % width;
    int y = i / height;

    float dx1 = x1-x;
    float dy1 = y1-y;
    float dx2 = x2-x;
    float dy2 = y2-y;

    //squared distance
    float d1 = dx1*dx1+dy1*dy1;//dist(x1, y1, x, y);
    float d2 = dx2*dx2+dy2*dy2;//dist(x2, y2, x, y);

    float wave1 = (1 + (sin(TWO_PI * d1/factorA + t))) * 0.5 * exp(-d1/factorB);
    float wave2 = (1 + (sin(TWO_PI * d2/factorA + t))) * 0.5 * exp(-d2/factorB);

    pixels[i] = color((wave1 + wave2) *255);
  }
  updatePixels();
  text((int)frameRate+"fps",10,15);
  //  endShape();
  t--; //Wave propagation
  //saveFrame("wave-##.png");
}

可以使用查找表进一步加快速度,例如sin()exp().

This can be sped up further using lookup tables for the more time consuming functions such as sin() and exp().

即使在javascript中,您也可以看到粗略的预览(需要调整数字):

You can see a rough (numbers need to be tweaked) preview running even in javascript:

var x1;
var y1;
var x2;
var y2;
var t = 0;

var factorA = 20*200;
var factorB = 80*200;
var numPixels;

var scaledWidth;

function setup() {
  createCanvas(400, 400);
  fill(255);
  frameRate(30);
  
  x1 = width /4;
  y1 = height /2;
  
  x2 = width * 3/4;
  y2 = height / 2;
  
  loadPixels();

  numPixels = (width * height) * pixelDensity();

  scaledWidth = width * pixelDensity();
}

function draw() {
  for (var i = 0, j = 0; i < numPixels; i++, j += 4) {
    var x = i % scaledWidth;
    var y = floor(i / scaledWidth);
    
    var dx1 = x1 - x;
    var dy1 = y1 - y;
    var dx2 = x2 - x;
    var dy2 = y2 - y;
    
    var d1 = (dx1 * dx1) + (dy1 * dy1);//dist(x1, y1, x, y);
    var d2 = (dx2 * dx2) + (dy2 * dy2);//dist(x2, y2, x, y);
    
    var wave1 = (1 + (sin(TWO_PI * d1 / factorA + t))) * 0.5 * exp(-d1 / factorB);
    var wave2 = (1 + (sin(TWO_PI * d2 / factorA + t))) * 0.5 * exp(-d2 / factorB);
    
    var gray = (wave1 + wave2) * 255;
    
    pixels[j] = pixels[j+1] = pixels[j+2] = gray;
    pixels[j+3] = 255;
  }
  updatePixels();
  
  text(frameRate().toFixed(2)+"fps",10,15);

  t--; //Wave propagation

}

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

因为您正在使用数学合成图像,所以将其编写为GLSL着色器可能更有意义.请确保查看 PShader教程以获取更多信息.

Because you're using math to synthesise the image, it may make more sense to write this as a GLSL Shader. Be sure sure to checkout the PShader tutorial for more info.

更新:

这是GLSL版本:代码的hacky少了,可读性更高:

Here's a GLSL version: code is less hacky and a lot more readable:

float t = 0;
float factorA = 0.20;
float factorB = 0.80;

PShader waves;

void setup() {
  size(400, 400, P2D);
  noStroke();

  waves = loadShader("waves.glsl");
  waves.set("resolution", float(width), float(height));
  waves.set("factorA",factorA);
  waves.set("factorB",factorB);
  waves.set("pt1",-0.5,0.0);
  waves.set("pt2",0.75,0.0);  
}

void draw() {
  t++;
  waves.set("t",t);

  shader(waves);
  rect(0, 0, width, height);  
}
void mouseDragged(){
  float x = map(mouseX,0,width,-1.0,1.0);
  float y = map(mouseY,0,height,1.0,-1.0);
  println(x,y);
  if(keyPressed) waves.set("pt2",x,y);
  else           waves.set("pt1",x,y);
}
void keyPressed(){
  float amount = 0.05;
  if(keyCode == UP)     factorA += amount;
  if(keyCode == DOWN)   factorA -= amount;
  if(keyCode == LEFT)   factorB -= amount;
  if(keyCode == RIGHT)  factorB += amount;
  waves.set("factorA",factorA);
  waves.set("factorB",factorB);
  println(factorA,factorB);
}

waves.glsl:

And the waves.glsl:

#define PROCESSING_COLOR_SHADER

uniform vec2 pt1;
uniform vec2 pt2;
uniform float t;

uniform float factorA;
uniform float factorB;

const float TWO_PI = 6.283185307179586;

uniform vec2 resolution;
uniform float time;


void main(void) {
  vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;

  float d1 = distance(pt1,p);
  float d2 = distance(pt2,p);

  float wave1 = (1.0 + (sin(TWO_PI * d1/factorA + t))) * 0.5 * exp(-d1/factorB);
  float wave2 = (1.0 + (sin(TWO_PI * d2/factorA + t))) * 0.5 * exp(-d2/factorB);

  float gray = wave1 + wave2;

  gl_FragColor=vec4(gray,gray,gray,1.0);
}

您可以将拖动用作第一个点,并按住一个键并拖动作为第二个点. 此外,使用UP/DOWNLEFT/RIGHT键更改 factorA factorB .结果看起来很有趣:

You can use drag for first point and hold a key and drag for the second point. Additionally, use UP/DOWN, LEFT/RIGHT keys to change factorA and factorB. Results look interesting:

此外,您还可以从

Also, you can grab a bit of code from this answer to save frames using Threads (I recommend saving uncompressed).

这篇关于处理3改进密集型数学计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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