読者です 読者をやめる 読者になる 読者になる

aa develop

開発と成長

ProcessingのblendMode()の使い方

Processing

ProcessingではblendMode()で色を重ねたときにどう表示するかを決定するすることができます。 これを使うと発光表現を簡単に作ることができるらしいのですが、いまいち公式リファレンスを読んでも何がどうなるかがわからず敬遠していました。

なので今回はblendModeの設定だけを変えて同じものを描画し、色を重ねたときにどうなるかを検証してみました。

BLEND

f:id:aa_debdeb:20161103171826j:plain

BLENDはデフォルトの設定です。 上段は3色を、下段は単色を重ねています。左側は背景が黒色、右側は背景が白色になっています。 そのため、全部で4つの設定を比較しています。 以下では、同じものをblendModeの設定だけ変えて描画しています。 BLENDの場合は、alpha値を設定しないと色を重ねても上書きされるだけです。

ADD

f:id:aa_debdeb:20161103172213j:plain

ADDでは、色を重ねるとどんどん白に近づいていきます。そのため、背景が白い場合は何も表示されません。ADDで色を重ねると発光表現になるみたいです。

SUBTRACT

f:id:aa_debdeb:20161103172739j:plain

SUBTRACTはADDと逆で、白からどんどん色を抜いていき、黒に近づいていきます。白に色を重ねた場合、表示されるのがその補色なので使用するのが難しそうです。

DARKEST

f:id:aa_debdeb:20161103173415j:plain

DARKESTは重ねたときに各RGB値の値が小さい方を新たなRGB値にして表示します。背景が黒の場合は(R, G, B) = (0, 0, 0)なので何も表示されません。

LIGHTEST

f:id:aa_debdeb:20161103173421j:plain

LIGHTESTはDARKESTと逆に、重ねたときに各RGB値の値が大きい方を新たなRGB値にして表示します。背景が白の場合は(R, G, B) = (255, 255, 255)なので何も表示されません。

DIFFERENCE

f:id:aa_debdeb:20161103173429j:plain

DIFFERENCEは背景色と重ねた色の差をもとに新たな色を決定しています。

EXCLUSION

f:id:aa_debdeb:20161103173438j:plain

EXCLUSIONはDIFFERENCEと同じ処理をしていますが、その処理がやや抑えめになっています。

MULTIPLY

f:id:aa_debdeb:20161103173446j:plain

MULTIPLYでは重ねると色が暗くなります。

SCREEN

f:id:aa_debdeb:20161103173457j:plain

SCREENはMULTIPLYと逆で、重ねると色が明るくなります。これも発光表現に使えるようです。

まとめ

基本的には、ADDとSUBTRACT、LIGHTESTとDARKEST、SCREENとMULTIPLYがそれぞれ黒背景用、白背景用で対照になっているようです。 SUBTRACTとDARKESTは重ねた色の補色が表示されるので、感覚的に使うのは難しそうです。

ちなみにBLENDモードで重ねる色のalpha値を設定したとき(alpha = 150)は以下のようになります。

f:id:aa_debdeb:20161103180957j:plain

以下、コードです。マウスクリックでblendModeの設定を変更することができます。 Processing3で動作を確認しています。 Processing2ではblendModeがうまく機能しませんでした。

/**
* test for blendMode()
*
*/

int modeId = 0;
int[] modes = {BLEND, ADD, SUBTRACT, DARKEST, LIGHTEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN};
String[] modesStr = {"BLEND", "ADD", "SUBTRACT", "DARKEST", "LIGHTEST", "DIFFERENCE", "EXCLUSION", "MULTIPLY", "SCREEN"};

void setup(){
  size(600, 600);
}

void mousePressed(){
  modeId++;
  if(modeId == modes.length){
    modeId = 0;
  }
}

void draw(){
  blendMode(BLEND);
  background(255);
  noStroke();
  fill(0);
  rect(0, 0, width / 2, height);
  stroke(128);
  strokeWeight(1);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);
  fill(128);
  text(modesStr[modeId], 20, 20);
  
  blendMode(modes[modeId]);
  pushMatrix();
  translate(width / 4, height /4);
  drawPolyCircles();
  popMatrix();
  pushMatrix();
  translate(width / 4 * 3, height /4);
  drawPolyCircles();
  popMatrix();
  pushMatrix();
  translate(width / 4, height /4 * 3);
  drawMonoCircles();
  popMatrix();
  pushMatrix();
  translate(width / 4 * 3, height /4 * 3);
  drawMonoCircles();
  popMatrix();
}

void drawPolyCircles(){
  color[] colors = {color(255, 96, 96),
                    color(96, 255, 96),
                    color(96, 96, 255)}; 
  noStroke();
  for(int i = 0; i < 3; i++){
    fill(colors[i]);
    pushMatrix();
    rotate(i * TWO_PI / 3 - HALF_PI);
    ellipse(50, 0, 150, 150);
    popMatrix();
  }
}

void drawMonoCircles(){
  noStroke();
  for(int i = 0; i < 3; i++){
    fill(color(255, 96, 96));
    pushMatrix();
    rotate(i * TWO_PI / 3 - HALF_PI);
    ellipse(50, 0, 150, 150);
    popMatrix();
  }
}