From BlenderWiki

Jump to: navigation, search

Blender 2.72: Freestyle NPR レンダリング

Freestyle for Cycles

Freestyle ラインレンダリングエンジンが Blender 2.67で Blender Internal(BI:Blender内部レンダー)に統合されたのに加え、Cycles にも統合されました(D632)。Freestyle はアニメだけでなく、建築物のビジュアライゼーション、見取り図の作成、コンピュータ生成のスケッチなどに利用できる、様々なノンフォトリアル(NPR: Non PhotoRealistic)スタイルのラインレンダリングオプションを Cycles に提供します。

Cycles/Freestyle による画像(Choi Youn-Soo氏作)

大半の Freestyle のオプションは Cycles と BI の両方で同じように動作します。Cycles 用 Freestyle でのラインテクスチャは、シェーダノードから設定されます(BI 用 Freestyle は従来のテクスチャマッピングと影響パネルを採用しています)。また、二つの Freestyle 用のシェーダノードが追加されています。

  • Line Style Output(ラインスタイル出力) ノード:テクスチャの色とアルファ透過度をラインスタイルのベースカラーとベースアルファ透過度とどうミックスするかを指定します。
  • UV Along Stroke(UVストローク追従) 入力ノード:(ストローク先端有り無しの両方で)ストロークに追従するテクスチャを定義した UV マップへのアクセスを与えます。これらの UV マップは Freestyle レンダリング処理中のみ利用可能になります。そのため、UV Along Stroke(UVストローク追従)ノードを、従来のメッシュデータの一部としてすでに設定されている現存の UV マップを取る、UV Map(UVマップ)入力ノードで置き換えることはできません。

下の画像は、花柄のテクスチャ画像をストロークに沿ってマッピングする、典型的なシェーダノードのスクリーンキャプチャです。

UV Along Stroke(UVストローク追従)入力ノードは Freestyle によって生成されたストロークに追従した UV マップを取り出し、Image Texture(画像テクスチャ)ノードの Vector(ベクトル)入力チャンネルに供給します。テクスチャ画像が Image Texture(画像テクスチャ)ノード内で選択され、その色が Line Style Output(ラインスタイル出力)ノードのアルファチャンネルに供給されます。

Alpha Factor(アルファ係数)を 1 に設定すると、テクスチャ画像はアクティブラインスタイルの元のアルファ透過度(Freestyle Line Style(ラインスタイル)パネルに表示)を置き換えます。

一方、Line Style Output(ラインスタイル出力)ノードで Mix(ミックス)ブレンドモードを選択し、Color Factor(色係数)を 0 にすると、アクティブなラインスタイルで指定されたグラデーションのラインカラーがストロークに沿って適用されます。

Cycles での Freestyle テクスチャストローク (File:Blender 272 textured strokes in cycles.blend)

スクリーンキャプチャ画像に表示されているテクスチャ画像 (FS_floral_brush.png) が、先端付きの Freestyhle ブラシ画像であることに注目してください。具体的には、画像の上半分がストロークボディのシームレスな水平タイルとして、下半分はストロークの両端として使用されています。

制限

  • 3Dビューでの Freestyle プレビューレンダリングは、Cyclesではまだ対応していません。
  • Color(カラー)/Alpha(アルファ)/Thickness(厚さ)の Material(マテリアル)モディファイアーは、Material Attribute(マテリアルアトリビュート)が Line Color(ラインカラー:次の項を参照)、またはその RGB 成分になっている時のみ期待通りに動作します。

BI と Cycles 用の Line color(ラインカラー)プロパティ

Freestyle の Line(ライン)マテリアルプロパティ

新しくマテリアル ID データブロックに、Freestyle line というFreestyleの色を指定するプロパティが導入されました。Cycles と BI の両方で共通で使用するマテリアルカラーのプロパティがないのがその理由です(BI マテリアルのディフューズカラーという例外はありますが、これは Cycles のシェーダノードが無効な場合に使用されます)。この新しいカラープロパティは、Freestyle レンダーに使われているレンダリングエンジンが何であっても、確実にマテリアル毎にラインカラーを指定する方法を提供します。

さらに、line color priority(優先度) (図のUI 内のラインカラーの隣)という、マテリアル境界で競合するラインカラーの順序を指定するプロパティも導入されました。このラインカラープロパティの使用ケースの詳細は、Freestyle 開発者ブログの記事(外部リンク(英文))にあります。


Freestyle Python API の更新

Freestyle Python API の実装が多数のコード更新の貢献により、大幅に改良されました((D319D545D623D752)。 Freestyle は、コーダーアーティストに Freestyle Python スクリプティングのサンプルを提供することを目的とした、Python で書かれた多数の定義済みスタイルモジュールを携えて登場しました。そのため、現存の Python スクリプトのコード可読性は、Freestyle の開発の大きな懸念の一つとなっています。このことは Freestyle スタイルモジュールへのより Python ライクなコーディング慣習の適用により、レンダリングスピードが改善されることにも表れています。

これらの作業要素は、何度も繰り返されたレビューにも耐え、コードの可読性と実行パフォーマンスが改善するよう注意深く修正されたパッチ集の貢献によって解決されました。

目に見える API の更新の一部:

  • ビルトインの関数、reversed() が Stroke オブジェクトに適用された時、ストロークの最後からストローク頂点を反復する新規イテレータが返ります。他の Python シーケンスオブジェクトと同様の動作をします。実際には Stroke.stroke_vertices_end() と同じです。
  • StrokeVertexIterator が .incremented().decremented().reversed() メソッドが追加、それぞれ新規のインクリメント、デクリメント、リバースイテレータオブジェクトを返します。
  • Interface0DIterator と StrokeVertexIterator のコンストラクタが Stroke オブジェクトを受け付けるように(実際には Stroke.vertices_begin()Stroke.stroke_vertices_begin()のそれぞれと同じ)。
  • また、これらのイテレータクラスも新しく .at_last プロパティを持つように。イテレータが最後の要素を示す時、値が true になります。このプロパティはビルトインの next() 関数をイテレータに適用し、大幅にパフォーマンスが向上した時の反復を止めるのに必要です。

下の Python コードは関数(サンプルでは Normal2DF0D)を使用し、ストローク頂点毎に適用する典型的なストロークシェーダです。このユーザ定義の shade() メソッド内でのストローク頂点全体の反復は、API の変更が文書化される以前の、古い文法で書かれた物であることに注意してください。

class myNormalDependentStrokeShader(StrokeShader):
    def __init__(self):
        StrokeShader.__init__(self)
        self.getNormal = Normal2DF0D()
    def shade(self, stroke):
        it = stroke.stroke_vertices_begin()
        while not it.is_end:
            normal = self.getNormal(Interface0DIterator(it))
            vertex = it.object
            ...
            # vertex attribute updates here
            ...
            it.increment()

Python API の拡張により、shade() メソッドは下のように非常に単純化できるようになりました。

class myNormalDependentStrokeShader(StrokeShader):
    def __init__(self):
        StrokeShader.__init__(self)
        self.getNormal = Normal2DF0D()
    def shade(self, stroke):
        it = Interface0DIterator(stroke)
        for vertex in it:
            normal = self.getNormal(it)
            ...
            # vertex attribute updates here
            ...

また、next() 関数と、イテレータの .object プロパティを混合できないことにも述べておきます。これは next() がまずイテレータをインクリメントし、その後、さっき指していたオブジェクトを返すためです(最初の要素は例外で、インクリメント処理なしで返します)。

謝辞

Cycles での Freestyle ラインレンダリングのコードレビューをしてくださった Thomas Dinges 氏と Sergey Sharybin 氏へ。Freestyle Python API の更新に貢献してくださった Folkert de Vries (flokkievids)氏に特に感謝します。