Dev:JA/Ref/Release Notes/2.70/Freestyle
目次
Blender 2.70: Freestyle NPR レンダリング
はじめに
Freestyle は高いプログラミング性があるよう設計された、ノンフォトリアリスティック(NPR)レンダリングエンジンで、ユーザが Python プログラミング言語を使用することで、自作のラインスタイルオプションを開発できます。
Blender 2.70リリースには、従来のアプリケーションプログラム(sytle モジュール)を壊す恐れのある、Freestyle Pyhotn アプリケーションプログラムインターフェイス(API)の大幅な見直しが盛り込まれおり、現在、2.7x シリーズではいくつかの後方互換性が失われていることが確認されています。Blender 2.67-2.69用に書かれた Python のスタイルモジュールは(少し)コードを更新する必要があるでしょう。また、Freestyle のレンダリング結果内にアーティストが見てわかる影響がないよう、API の変更は完全に内部的な物になっていることも付け加えておきます。
その1: Python API モジュールの再編成
Freestyle に関連する Python モジュールが bpy モジュールとそのサブモジュールに一致するよう再編成されました。(T37565)。この API の更新は、現在の Freestyle の実装に見られる以下の問題を解決することを目的としています。
- Python で書かれたスタイルモジュール用に構築された Freestyle API は、論理的な構造ではありませんでした。API モジュールは一部が実装されている言語(C と Python)に関して構造化されており、一部は実装の役割(述語(predicates)、チェーンイテレータなど)を元にしています。
- Freestyle のすべての Python スクリプト、つまり API モジュールとアプリケーションプログラム(スタイルモジュール)は同じ 'release/scripts/freestyle/style_modules' ディレクトリに格納されています。このことは、新規ユーザがスタイルモジュールを探すのを難しくしています。
新しい Python モジュールの構造
新しい Python モジュールディレクトリの構造は以下のように編成されました。
release/scripts/freestyle/modules
- Freestyle API モジュールrelease/scripts/freestyle/styles
- 定義済みスタイルモジュール
Python では、Freestyle API モジュールは以下のように再編成されました。
freestyle
- 以下のサブモジュールを詰め込んだだけのトップレベルのパッケージ。freestyle.types
- コアデータ構造のクラスと、ユーザ定義のスタイライゼーションルールのベースクラス(chainingiterators、predicates、functions、shaders)。freestyle.chainingiterators
- 定義済みチェーンイテレータ。freestyle.predicates
- 定義済みの0Dと1Dの述語。freestyle.functions
- 定義済みの0Dと1Dの関数。freestyle.shaders
- 定義済みストロークシェーダ。freestyle.utils
- スタイルモジュール作成用のユーティリティ関数。
API 改訂前後のコードサンプル
API 変更の影響を japanese_bigbrush.py スタイルモジュールを例に挙げ、以下に示します。
以前の API 構造(API 更新前)では、import ステートメントはスタイルモジュールの最初に、次のように記述します。
from freestyle import BezierCurveShader, ChainSilhouetteIterator, ConstantColorShader, \
ConstantThicknessShader, IntegrationType, Operators, QuantitativeInvisibilityUP1D, \
SamplingShader, TextureAssignerShader, TipRemoverShader
from Functions0D import pyInverseCurvature2DAngleF0D
from PredicatesB1D import pyLengthBP1D
from PredicatesU0D import pyParameterUP0D
from PredicatesU1D import pyDensityUP1D, pyHigherLengthUP1D, pyHigherNumberOfTurnsUP1D
from logical_operators import NotUP1D
from shaders import pyNonLinearVaryingThicknessShader, pySamplingShader
更新後の Python API では、これらの import ステートメントは次のように記述します。
from freestyle.chainingiterators import ChainSilhouetteIterator
from freestyle.functions import pyInverseCurvature2DAngleF0D
from freestyle.predicates import (
NotUP1D,
QuantitativeInvisibilityUP1D,
pyDensityUP1D,
pyHigherLengthUP1D,
pyHigherNumberOfTurnsUP1D,
pyLengthBP1D,
pyParameterUP0D,
)
from freestyle.shaders import (
BezierCurveShader,
ConstantColorShader,
ConstantThicknessShader,
SamplingShader,
TextureAssignerShader,
TipRemoverShader,
pyNonLinearVaryingThicknessShader,
pySamplingShader,
)
from freestyle.types import IntegrationType, Operators
利用のしやすさの点からいえば、新しい構造はスタイルモジュール作者が関連する Python constract を freestyle.* サブモジュールから非常に簡単に探し出すことができます。ちなみに、従来と新しいモジュール構造の間にに機能の違いはありません(レンダリング結果に見た目の影響はありません)。
その2: Python イテレータプロトコルへの対応の強化
Freestyle のイテレータの、Python イテレータプロトコルへの対応が強化されました(T38213)。StrokeVertexIterator(ストロークシェーダ内で使用)を例にとると、ストローク頂点全体のイテレーションは下記のように、C++ スタイルのイテレータオブジェクト(it
)を使用して書かれていました。
it = stroke.stroke_vertices_begin()
while not it.is_end:
# do something
it.increment()
Blender 2.70からは同じイテレーションを、下記のように Python イテレータプロトコルを使用して記述できるようになりました。
it = iter(stroke)
for vert in it:
# do something
二つめの頂点のイテレーション形式は、以前も使用可能でしたが、大半のユーザの想像とは異なった動作をしていました。問題はこのイテレータオブジェクト it
と、for ループが同期しなくなることです。
特に it.object
は、for ループ内の vert
と思しき物の次の頂点を参照します。
イテレータオブジェクトがループ内の頂点毎に処理を実行するのに、引数として述語と関数を渡すことがよくあり、イテレータオブジェクトと for ループの間で矛盾が発生するため、二つめの表記は役に立っていませんでした。現在、この for ループの形式は完全に使用可能になっており、イテレータと for ループは頂点群を同期して通り抜けます。
さらに、next(it) も確実に動作するようになりました。下はその例です。
it = iter(stroke)
first_vert = next(it)
なお、頂点全体の逆方向のイテレーションは下記のように書けます。
it = stroke.stroke_vertices_end()
for svert in it:
# do something
謝辞
タスク T37565 と T38213を通じた API 更新のメインの貢献者は Folkert de Vries (flokkievids)氏です。また、コードレビューと議論を行った Campbell Barton 氏にも感謝します。