HEXA BLOG

プログラム

HEXA BLOGプログラム2014.6.27

セルテクスチャに挑戦!

皆さん、こんにちは!

 

千里の道も一歩から!のビッシーです

 

今年の目標はプロシージャル技術の研究ということで、
前回に引き続きプロシージャルテクニックを実践していきます!

 

 今回は代表的なプロシージャルテクスチャ技法の一つ
「セルテクスチャ」をベースにプロシージャルテクスチャを作成していきます。

 

そもそもプロシージャルテクスチャとは何ぞや?
言葉で説明することはなかなか難しいので、
今回は、目的であるセルテクスチャに至るまでの過程から
プロシージャルの考え方を感じ取ってもらえればと思います。

 

1.プロシージャルテクスチャとは?

プロシージャルテクスチャリングを一言で表現すると、
「一連の手続き(プロシージャ)を使って画像(テクスチャ)を表現する」ことです。

 

画像処理ができるプログラミング環境があれば、
どんな環境でも実装していくことができると思います。

 

今回のサンプルでは、 JavaScriptを利用してプロシージャルテクスチャを実装しました。
画像の表示、保存にはHTML5 Canvas機能を使っています。

 

サンプルは記事の最後に掲載していますので、ぜひ触ってみてください

 

2.点を描く

これからテクスチャ(画像)を描いていきますので、 まずはキャンパスが必要になります。 20140627_tex001

さすがに真っ黒なキャンパスは寂しいので、
セルテクスチャに取り組むウォーミングアップとして、点(ドット)の描画を行います。

 

ペイントソフトでは鉛筆でドットを描いていくことができますが、
プロシージャルの世界では、手続き(プロシージャ)を使って点を表現します。

 

プロシージャルで画像を表現するにあたって、
画像をピクセルデータの集まりと考えると複雑化するため、
2次元画像は「xとyという引数を受け取ってcolorを返す関数」として考えます。

 

すると「点を描画する」=「点が存在するピクセルでは点の色を返す関数」と定義できます.

 

例えば、点列plistがあるとして、その点を描画する関数は下のように定義できます.

// 点を打つ関数(dstは背景色)
function(x,y,dst) {
    for(i=0; i<plist.length; ++i) {
        // 点が存在しているピクセルの場合
        if( x==plist[i].x && y==plist[i].y ) {
            return color;
        }
    }
    return dst;
}

plist自体はデータとして予め準備してもよいですがランダム列であればよいので、
サンプルでは シード値からプログラムで自動生成させるようにしました。

20140627_tex002

 

これで、星空のような画像が出来ました

 

 

3.水玉を描く

さすがにドットでは迫力にかけるので、 次はドットに面積を持たせてみます。

 

円は関数で表すと、円の内外判定関数になります。

 

「ある点が円の内部である」というのは、
「『ある点』と『円の中心点』の距離が『円の半径』未満である」
と言い換えることが出来ます。

 

この円の描画関数を先ほどの点描画関数に加筆すると、下のようになります。

function(x,y,dst) {
    for(i=0; i<plist.length; ++i) {
        // 円内部のピクセルの場合
        var d = pointlen(x, y, plist[i][0], plist[i][1]);
        if( d < r ) {
            // 色を線形補間して表示
            return alerp(color2, color1, d/r);
        }
    }
    return dst;
};

20140627_tex003

 

修正はわずかですが、見た目の効果は大きく変わりましたね

 

4.セルを描く

ウォーミングアップが終わったので、本題のセルテクスチャに取り組みます

 

セルテクスチャは、細胞のように小さな領域で充足されたテクスチャです。
主に爬虫類の表皮等の有機的な表現に向いている手法です。

20140627_tex007

 

シンプルなセルテクスチャは、
2次元空間のランダム点中で最近になる点との距離によって
色を補間することで表現できます。

function(x,y,dst) {
    // 最近点までの距離を計算
    var dmin = 100000.0;
    for(i=0; i<plist.length; ++i) {
        var d = pointlen(x, y, plist[i][0], plist[i][1]);
        if( d < dmin ) {
            dmin = d;
        }
    }
    // 距離に応じてカラーを線形補間
    return alerp(color2, color1, dmin/k);
}

20140627_tex004

 

式は単純なのですが、
ボコボコした何とも言えないテクスチャが仕上がりました

 

5.複雑なセルを描く

セルテクスチャの関数を組み合わせることで、
複雑なセル模様を構築することができます。

 

4.では最近点の距離を使いましたが、より見た目を複雑にするため、
距離の近い4点を集めて重み付合成することで表現を拡張します。

 

距離値でそのまま重み付き合成をしてしまうと値の範囲が広くなってしまうので、
事前にランダムなサンプル点を取得して、
セルの計算値の最大値と最小値の予測値を計算し、
重みを[0-1]の間にスケールして計算するようにします。

 

最終的には、見た目の調節のためパラメータの修正や、
カラー補正処理などを加えて生成される画像を整えていくと下のようになりました。

20140627_tex005

プログラムは長くなったため掲載は省きますが、
サンプルに含めていますので気になる方は確認してみて下さい

 

ここまでくるとパラメータが複雑化するため、パラメータを乱数から生成するようにして、
代わりに乱数のシード値をパラメータとして設定できるようにしておくと、
テクスチャの生成を試しやすくなります

 

6.サンプル

今回のサンプルは、 HTML5 CanvasとJavascriptで実装しています。

 

20140627_celltexture_sample

 

※動作確認はChromeブラウザで行いましたので、他のブラウザでは動作未保証です※

 

乱数のシードを返ることで、見た目の異なる画像を生成することができます。 20140627_tex006 

 

 

 

他にもプロシージャルテクスチャにはノイズ関数を利用したものや、
フラクタル関数を利用するものなどがあります。

 

今後機会があれば紹介していきたいと思います。

 

それでは

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE