书名:代码本色:用编程模拟自然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
目录
4.13 图像纹理和加法混合
1、加法混合
-
计算机图形学有很多颜色混合算法,这些算法通常称作“混合(blend)模式”。
-
在Processing中,如果在一幅图像之上绘制另一幅图像,默认显示最上层图像——这通常称为“常规”混合模式。
-
如果图像有一定的透明度(就像模拟烟效程序中用到的图像),Processing会使用alpha透明度混合算法将一定比例的背景像素和前景像素结合起来,混合比例根据alpha值确定。
-
除此之外,我们还可以使用其他混合模式,对粒子系统来说,有一种混合模式非常适
用,它就是“加法(additive)模式”。
Processing中的加法混合模式是由Robert Hodgin开发的,他在粒子系统和力的模拟上很有建树。他开发了Magnetosphere,后来成为iTunes的可视化效果。 -
实际上,加法混合是最简单的混合算法之一,它只是将两个图层的像素值相加(当然,相加结果的最大值是255),最后形成的效果就是:随着图层增多,色彩变得越来越亮。
-
为了在Processing中使用加法混合,你需要使用P2D或者P3D渲染器。
2、示例
示例代码4-9 加法混合
ParticleSystem ps;
PImage img;
void setup() {
size(640, 360, P2D);
// Create an alpha masked image to be applied as the particle's texture
img = loadImage("texture.png");
ps = new ParticleSystem(0, new PVector(width/2, 50));
}
void draw() {
// Additive blending!
blendMode(ADD);
background(0);
ps.run();
for (int i = 0; i < 10; i++) {
ps.addParticle();
}
}
Particle.pde
class Particle {
PVector pos;
PVector vel;
PVector acc;
float lifespan;
// Another constructor (the one we are using here)
Particle(PVector l) {
// Boring example with constant acceleration
acc = new PVector(0,0.05,0);
vel = new PVector(random(-1,1),random(-1,0),0);
vel.mult(2);
pos = l.copy();
lifespan = 255;
}
void run() {
update();
render();
}
// Method to update position
void update() {
vel.add(acc);
pos.add(vel);
lifespan -= 2.0;
}
// Method to display
void render() {
imageMode(CENTER);
tint(lifespan);
image(img,pos.x,pos.y);
}
// Is the particle still useful?
boolean isDead() {
if (lifespan <= 0.0) {
return true;
} else {
return false;
}
}
}
ParticleSystem.pde
class ParticleSystem {
ArrayList<Particle> particles; // An arraylist for all the particles
PVector origin; // An origin point for where particles are birthed
PImage tex;
ParticleSystem(int num, PVector v) {
particles = new ArrayList(); // Initialize the arraylist
origin = v.get(); // Store the origin point
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
}
}
void run() {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = particles.get(i);
p.run();
if (p.isDead()) {
particles.remove(i);
}
}
}
void addParticle() {
particles.add(new Particle(origin));
}
void addParticle(Particle p) {
particles.add(p);
}
// A method to test if the particle system still has particles
boolean dead() {
if (particles.isEmpty()) {
return true;
}
else {
return false;
}
}
}
网友评论