ブレンドについて
■ブレンドとは?
Photoshop などの、画像編集ツールではおなじみの機能です。
ブレンドを使用すると、「任意の表示オブジェクト」と「背景」とで、色の合成を行う事ができます。
ブレンドの種類として、14 パターンのモードが用意されています。
色の演算は、1ピクセルごとに行われ、全ピクセルが変換されます。
■ブレンドモード利用時の注意点
■Flash Player 9 以前の場合
幅と高さが 2880 ピクセルまでのグラフィックに適用できます。
グラフィックのサイズがこの範囲を超えてしまうと、ブレンドが動作しません。
■Flash Player 10 の場合
幅と高さが 8192 ピクセルまでのグラフィックに適用できますが、総ピクセル数は 16777216 までとなります。(幅が 8192 なら高さは 2048 まで)
グラフィックのサイズがこの範囲を超えてしまうと、ブレンドが動作しません。
■Flash Player 11 以降の場合
ピクセルサイズの制限はありません。
メモリ不足の場合、ブレンドが動作しません。
表示オブジェクトにブレンドを適用する
サンプルをダウンロード
■ブレンドを使用する
ブレンドは、表示オブジェクトであれば利用可能です。
表示オブジェクトにブレンドを適用するには、blendMode プロパティを使用します。
以下の表にある、定数をセットします。
■ブレンドモードの種類
定数 | 文字列 | 名称 |
BlendMode. | "normal" | 標準 |
BlendMode. | "layer" | レイヤー |
BlendMode. | "multiply" | 乗算 |
BlendMode. | "screen" | スクリーン |
BlendMode. | "lighten" | 比較(明) |
BlendMode. | "darken" | 比較(暗) |
BlendMode. | "difference" | 差の絶対値 |
BlendMode. | "add" | 加算 |
BlendMode. | "subtract" | 減算 |
BlendMode. | "invert" | 反転 |
BlendMode. | "alpha" | アルファ |
BlendMode. | "erase" | 消去 |
BlendMode. | "overlay" | オーバーレイ |
BlendMode. | "hardlight" | ハードライト |
BlendMode. | "shader" | シェーダー (Flash 10 以降) |
■使用例
表示オブジェクト mc を加算でブレンドする
import flash.display.BlendMode;
mc.blendMode = BlendMode.ADD;
表示オブジェクト mc を減算でブレンドする
import flash.display.BlendMode;
mc.blendMode = BlendMode.SUBTRACT;
ブレンドの種類について
■標準 (BlendMode.NORMAL)
ブレンドを使用していない状態です。通常の表示です。
素材 | ⇒ | 結果 |
■レイヤー (BlendMode.LAYER)
複数のレイヤーを持つ表示オブジェクトを半透明にすると、以下のように表示されます。
レイヤーごとに半透明が適用されるので、重なる部分が透けて表示されます。
素材 | ⇒ | 半透明を適用 |
ブレンドで「レイヤー」を適用すると、描画結果に対して半透明がかかるようになります。
重なる部分が透けて表示される事はありません。
素材 | ⇒ | 半透明を適用 |
■乗算 (BlendMode.MULTIPLY)
シャドウや深度効果に使用します。
黒色に近づけるのに最適です。
グラフィックが黒色であるほど、結果は黒色に近づきます。
グラフィックが白色であるほど、結果に影響はありません。
背景 | + | ソース | ⇒ | 結果 |
乗算は、以下の計算が行われます。
各カラーは、「0 ~ 255」までありますが、この値を「0.0 ~ 1.0」までの小数値と考えます。
「背景」と「小数値」を乗算して結果を出力します。
乗算の変換式(透過成分は除外)
新しい赤色 = (ソースの赤色 / 255) * 背景の赤色;
新しい緑色 = (ソースの緑色 / 255) * 背景の緑色;
新しい青色 = (ソースの青色 / 255) * 背景の青色;
■スクリーン (BlendMode.SCREEN)
ハイライトなどに使用します。
白色に近づけるのに最適です。
グラフィックが白色であるほど、結果は白色に近づきます。
グラフィックが黒色であるほど、結果に影響はありません。
背景 | + | ソース | ⇒ | 結果 |
スクリーンは、以下の計算が行われます。
スクリーンの変換式(透過成分は除外)
新しい赤色 = 255 - ((255 - ソースの赤色) / 255) * (255 - 背景の赤色);
新しい緑色 = 255 - ((255 - ソースの緑色) / 255) * (255 - 背景の緑色);
新しい青色 = 255 - ((255 - ソースの青色) / 255) * (255 - 背景の青色);
スクリーンの変換式(最適化)(透過成分は除外)
新しい赤色 = ソースの赤色 + 背景の赤色 - ソースの赤色 * 背景の赤色 / 255;
新しい緑色 = ソースの赤色 + 背景の赤色 - ソースの赤色 * 背景の赤色 / 255;
新しい青色 = ソースの赤色 + 背景の赤色 - ソースの赤色 * 背景の赤色 / 255;
■比較(明) (BlendMode.LIGHTEN)
背景とソースのカラーを比較して、大きい(明るい)方を採用して出力します。
背景 | + | ソース | ⇒ | 結果 |
比較(明)は、以下の計算が行われます。
比較(明)の変換式(透過成分は除外)
新しい赤色 = (ソースの赤色 > 背景の赤色) ? ソースの赤色 : 背景の赤色;
新しい緑色 = (ソースの緑色 > 背景の緑色) ? ソースの緑色 : 背景の緑色;
新しい青色 = (ソースの青色 > 背景の青色) ? ソースの青色 : 背景の青色;
■比較(暗) (BlendMode.DARKEN)
背景とソースのカラーを比較して、小さい(暗い)方を採用して出力します。
背景 | + | ソース | ⇒ | 結果 |
比較(暗)は、以下の計算が行われます。
比較(明)の変換式(透過成分は除外)
新しい赤色 = (ソースの赤色 < 背景の赤色) ? ソースの赤色 : 背景の赤色;
新しい緑色 = (ソースの緑色 < 背景の緑色) ? ソースの緑色 : 背景の緑色;
新しい青色 = (ソースの青色 < 背景の青色) ? ソースの青色 : 背景の青色;
■差の絶対値 (BlendMode.DIFFERENCE)
背景とソースのカラーを比較します。
大きい値から小さい値を減算して結果を出力します。
背景 | + | ソース | ⇒ | 結果 |
差の絶対値は、以下の計算が行われます。
差の絶対値の変換式
新しい赤色 = (ソースの赤色 > 背景の赤色) ? (ソースの赤色 - 背景の赤色) : (背景の赤色 - ソースの赤色);
新しい緑色 = (ソースの緑色 > 背景の緑色) ? (ソースの緑色 - 背景の緑色) : (背景の緑色 - ソースの緑色);
新しい青色 = (ソースの青色 > 背景の青色) ? (ソースの青色 - 背景の青色) : (背景の青色 - ソースの青色);
■加算 (BlendMode.ADD)
光源の効果などに利用します。
白飛びするほど明るい表現に最適です。
グラフィックが白色であるほど、結果は白色に近づきます。
グラフィックが黒色であるほど、結果に影響はありません。
背景 | + | ソース | ⇒ | 結果 |
加算は、以下の計算が行われます。
「背景」と「ソース」のカラーを加算します。
計算した結果 255 より大きくなる場合は、255 となります。
加算の変換式(透過成分は除外)
新しい赤色 = ソースの赤色 + 背景の赤色;
新しい緑色 = ソースの緑色 + 背景の緑色;
新しい青色 = ソースの青色 + 背景の青色;
if(新しい赤色 > 255) 新しい赤色 = 255;
if(新しい緑色 > 255) 新しい緑色 = 255;
if(新しい青色 > 255) 新しい青色 = 255;
■減算 (BlendMode.SUBTRACT)
黒つぶれするほど暗い表現に最適です。
ソースのグラフィックが黒色であるほど、結果に影響はありません。
ソースのグラフィックが白色であるほど、結果は黒色に近づきます。
背景 | + | ソース | ⇒ | 結果 |
減算は、以下の計算が行われます。
「背景のカラー」から「ソースのカラー」を減算します。
計算した結果 0 より小さくなる場合は、0 となります。
加算の変換式(透過成分は除外)
新しい赤色 = 背景の赤色 - ソースの赤色;
新しい緑色 = 背景の緑色 - ソースの緑色;
新しい青色 = 背景の青色 - ソースの青色;
if(新しい赤色 < 0) 新しい赤色 = 0;
if(新しい緑色 < 0) 新しい緑色 = 0;
if(新しい青色 < 0) 新しい青色 = 0;
■反転 (BlendMode.INVERT)
背景カラーを反転して結果を出力します。
背景 | + | ソース | ⇒ | 結果 |
反転は、以下の計算が行われます。
加算の変換式(透過成分は除外)
新しい赤色 = (255 - 背景の赤色);
新しい緑色 = (255 - 背景の緑色);
新しい青色 = (255 - 背景の青色);
■アルファ (BlendMode.ALPHA)
アルファを動作させるには、親の表示オブジェクトのブレンドモードが、「BlendMode.LAYER (レイヤー)」である必要があります。
背景カラーの 赤 緑 青 成分はそのままで、透過成分はソースから出力します。
背景 | + | ソース | ⇒ | 結果 |
アルファは、以下の計算が行われます。
アルファの変換式(背景の透過成分は除外)
新しい赤色 = 背景の赤色;
新しい緑色 = 背景の緑色;
新しい青色 = 背景の青色;
新しい透過色 = ソースの透過色;
■消去 (BlendMode.ERASE)
消去を動作させるには、親の表示オブジェクトのブレンドモードが、「BlendMode.LAYER (レイヤー)」である必要があります。
背景カラーの 赤 緑 青 成分はそのままで、透過成分はソースから反転して出力します。
背景 | + | ソース | ⇒ | 結果 |
消去は、以下の計算が行われます。
消去の変換式(背景の透過成分は除外)
新しい赤色 = 背景の赤色;
新しい緑色 = 背景の緑色;
新しい青色 = 背景の青色;
新しい透過色 = 255 - ソースの透過色;
■オーバーレイ (BlendMode.OVERLAY)
背景のカラーが 127 以下であれば、乗算として動作します。
背景のカラーが 129 以上であれば、スクリーンとして動作します。
背景のカラーが 128 であるほど、ソースのカラーがそのまま出力されます。
背景のグラフィックが白色であるほど、結果は白色に近づきます。
背景のグラフィックが黒色であるほど、結果は黒色に近づきます。
背景 | + | ソース | ⇒ | 結果 |
オーバーレイは、以下の計算が行われます。
オーバーレイの変換式(透過成分は除外)
if(背景の赤色 > 129) 新しい赤色 = -255 + 2 * (ソースの赤色 + 背景の赤色) - ソースの赤色 * 背景の赤色 / 127.5;
else if(背景の赤色 < 127) 新しい赤色 = (ソースの赤色 / 127.5) * 背景の赤色;
else 新しい赤色 = ソースの赤色;
if(背景の緑色 > 129) 新しい緑色 = -255 + 2 * (ソースの緑色 + 背景の緑色) - ソースの緑色 * 背景の緑色 / 127.5;
else if(背景の緑色 < 127) 新しい緑色 = (ソースの緑色 / 127.5) * 背景の緑色;
else 新しい緑色 = ソースの緑色;
if(背景の青色 > 129) 新しい青色 = -255 + 2 * (ソースの青色 + 背景の青色) - ソースの青色 * 背景の青色 / 127.5;
else if(背景の青色 < 127) 新しい青色 = (ソースの青色 / 127.5) * 背景の青色;
else 新しい青色 = ソースの青色;
■ハードライト (BlendMode.HARDLIGHT)
ソースのカラーが 127 以下であれば、乗算として動作します。
ソースのカラーが 129 以上であれば、スクリーンとして動作します。
ソースのカラーが 128 であるほど、背景のカラーがそのまま出力されます。
ソースのグラフィックが白色であるほど、結果は白色に近づきます。
ソースのグラフィックが黒色であるほど、結果は黒色に近づきます。
背景 | + | ソース | ⇒ | 結果 |
ハードライトは、以下の計算が行われます。
ハードライトの変換式(透過成分は除外)
if(ソースの赤色 > 129) 新しい赤色 = -255 + 2 * (ソースの赤色 + 背景の赤色) - ソースの赤色 * 背景の赤色 / 127.5;
else if(ソースの赤色 < 127) 新しい赤色 = (ソースの赤色 / 127.5) * 背景の赤色;
else 新しい赤色 = 背景の赤色;
if(ソースの緑色 > 129) 新しい緑色 = -255 + 2 * (ソースの緑色 + 背景の緑色) - ソースの緑色 * 背景の緑色 / 127.5;
else if(ソースの緑色 < 127) 新しい緑色 = (ソースの緑色 / 127.5) * 背景の緑色;
else 新しい緑色 = 背景の緑色;
if(ソースの青色 > 129) 新しい青色 = -255 + 2 * (ソースの青色 + 背景の青色) - ソースの青色 * 背景の青色 / 127.5;
else if(ソースの青色 < 127) 新しい青色 = (ソースの青色 / 127.5) * 背景の青色;
else 新しい青色 = 背景の青色;
■シェーダー (BlendMode.SHADER) (Flash 10 以降)
■ Shader を指定する
このプロパティにアクセスすると、blendMode も連動して変化します。
■ Pixel Bender での実装について
入力変数(ビットマップ)は、最低でも2つ宣言します。
1枚目の入力ビットマップは、背景側です。
2枚目の入力ビットマップは、前面側です。
入力変数は image4 型、出力変数は、pixel4 型で統一します。
■使用例(Pixel Bender 側のコード)
「1枚目のイメージ」「2枚目のイメージ」間をマージする(ブレンド用)
<languageVersion : 1.0;>
// ------------------------------------------------------------
// カーネルを宣言
// ------------------------------------------------------------
kernel MyKernel < namespace:""; vendor:""; version:1; > {
// ------------------------------------------------------------
// 入力変数の宣言(ビットマップ)
// ------------------------------------------------------------
// 1枚目の入力イメージ(背景グラフィック)
input image4 src_back;
// 2枚目の入力イメージ(前面グラフィック)
input image4 src_front;
// ------------------------------------------------------------
// 出力変数の宣言(ピクセルカラー)
// ------------------------------------------------------------
output pixel4 dst;
// ------------------------------------------------------------
// パラメータ変数の宣言
// ------------------------------------------------------------
parameter float marge
<
minValue : 0.0;
maxValue : 1.0;
stepInterval : 0.01;
defaultValue : 0.25;
>;
// ------------------------------------------------------------
// ピクセルごとに実行される関数
// ------------------------------------------------------------
void evaluatePixel() {
// 現在のピクセル位置を取得する
float2 pos = outCoord();
// 位置を指定して、画像からピクセルカラーを取得する(ニアレストネイバー)
pixel4 color_b = sampleNearest(src_back , pos);
pixel4 color_f = sampleNearest(src_front , pos);
// ピクセルカラーを出力する
color_f.rgb = (color_f.rgb - color_b.rgb) * color_f.a + color_b.rgb;
color_f.a = 1.0;
dst = (color_f - color_b) * marge + color_b;
}
}
■使用例(Flash 側のコード)
シェーダーを渡して、ブレンドを動作させる
import flash.utils.ByteArray;
import flash.display.Shader;
import flash.display.ShaderData;
import flash.display.ShaderParameter;
import flash.display.Shape;
import flash.display.Graphics;
import flash.display.GradientType;
import flash.geom.Matrix;
// ------------------------------------------------------------
// 埋め込みアセットクラス
// ------------------------------------------------------------
[Embed( source="./blend.pbj" , mimeType="application/octet-stream" )]
var MyByteCode:Class;
// ------------------------------------------------------------
// 埋め込んだファイルから、ByteArray オブジェクトを作成する (自作クラス "MyByteCode" )
// ------------------------------------------------------------
var byte_code:ByteArray = new MyByteCode();
// ------------------------------------------------------------
// Shader オブジェクトを作成する
// ------------------------------------------------------------
var shader_obj:Shader = new Shader(byte_code);
// ------------------------------------------------------------
// パラメータに値を渡す
// ------------------------------------------------------------
// ShaderData オブジェクトを取得する
var shader_data:ShaderData = shader_obj.data;
// ShaderParameter オブジェクトを取得する
var parameter_marge:ShaderParameter = (shader_data["marge"]) as ShaderParameter;
// 値情報を渡す
if(parameter_marge){
parameter_marge.value = [ 0.8 ];
}
// ------------------------------------------------------------
// Shape オブジェクトを作成する
// ------------------------------------------------------------
var shape:Shape = (function():Shape{
// Shape オブジェクトを作成
var shape:Shape = new Shape();
// Shape に矩形を描画
var g:Graphics = shape.graphics;
var mtx:Matrix = new Matrix(256/1638.4 , 0 , 0 , 256/1638.4 , 128 , 128);
g.beginGradientFill ( GradientType.RADIAL , [0xff0000,0x00ff00,0x0000ff] , [1.0,0.5,0.0] , [0,128,255] , mtx );
g.moveTo ( 0 , 0 );
g.lineTo ( 0 , 256 );
g.lineTo ( 256 , 256 );
g.lineTo ( 256 , 0 );
g.endFill();
return shape;
})();
// ステージに配置する
stage.addChild(shape);
// ------------------------------------------------------------
// シェーダーを渡して、ブレンドを動作させる
// ------------------------------------------------------------
shape.blendShader = shader_obj;