Houdini 20.0 レンダリング

MantraレンダーでPythonを使用

On this page

概要

MantraがPythonをコールできる箇所が2つあります。これによりユーザがMantraのデータ処理を微調整することが可能になります。

  • IFDを解析する時、Mantraがプロパティを照会・変更するフィルタリング関数をコールすることができます。

  • Mantraが各タイルを完了した時点で関数をコールすることができます。これにより、より高度なレンダリング処理の統計分析を挿入することができます。

コールバックスクリプトでプロパティを照会・設定する方法

Mantraで動くPythonスクリプトにはmantraモジュールをインポートすることができます。mantraモジュールには2つの関数があります:

property("name")

プロパティ名に関連した値を返します。値は、たとえ1個のスカラー値であっても、常にリストで返ってきます。

setproperty("name", value)

この関数はプロパティ名の値を設定します。関数はフィルタリングコールバックでのみ動作します(タイルコールバックでは動作しません)。

フィルタリング

MantraがIFDファイルを解析中に実行したいPythonスクリプトを指定するためには、Mantra-Pオプションを使います。複数のスクリプトを指定する場合は、セミコロン(;)で区切ります。

MantraがPythonスクリプトを読み込んだ時にそれに渡す引数をオプションで指定することができます。これはフィルタリングスクリプトの動作を修正するときに指定します。

このスクリプトは以下の関数を定義することができます。スクリプトに関数を定義すると、IFDファイルを解析中にMantraは適切な位置で関数をコールします。Mantraはあなたが定義していない関数を無視します。

filterGeometry()

ジオメトリオブジェクトのロック解除をするray_endステートメントの前にコールされます。これはプログラムがgeometry:の設定を照会して、できるだけその設定を変更することができます。

filterMaterial()

Mantraにはプリミティブ単位基準で適用可能なマテリアルブロックがあります。この関数は、マテリアルがロック解除される前にコールされます。関数はマテリアルにプロパティを追加または変更することができます。

filterInstance()

インスタンスオブジェクトの設定をロック解除するray_endステートメントの前にコールされます。関数はobject:の設定を照会して、できるだけその設定を変更することができます。

filterLight()

ライトオブジェクトの設定をロック解除するray_endステートメントの前にコールされます。関数はlight:の設定を照会して、できるだけその設定を変更することができます。

filterFog()

フォグオブジェクトの設定をロック解除するray_endステートメントの前にコールされます。関数はfog:の設定を照会して、できるだけその設定を変更することができます。

filterCamera()

グローバルプロパティがレンダリングでロック解除される前にコールされます。これは通常はIFDの任意のオブジェクトの宣言の前に記述します。もし後に記述すると、グローバルプロパティを変更しても、おそらく何も効果がありません。

Mantraはライトやインスタンスの宣言の前にこの関数をコールするので、デフォルトのライトやインスタンスプロパティをここで設定することができます。Mantraは、ここで設定したインスタンス/ライトのプロパティを明示してプロパティを宣言していないオブジェクトに適用します。

filterCameraSegment()

ray_endステートメントの前にコールされて、カメラモーションセグメントの設定をロックします。

filterRender()

ray_raytraceコマンドの前にコールされます。IFD処理の時点で任意のプロパティを変更することはできません。しかし、統計や検証ではこのメソッドは利用可能なので便利です。

filterPlane()

Houdini 9.1では、画像平面の設定が今ではプロパティになっています(画像平面のプロパティを参照)。このフィルタリングコールバックは画像平面のプロパティをIFDを解析する時に照会/修正することが可能になります。

def filterPlane():
    print 'Defining plane:',
          mantra.property('plane:channel'),
          mantra.property('plane:variable')
    mantra.setproperty('plane:quantization', 'float')

filterEndRender()

画像をレンダリングした後にコールされます。

filterQuit()

Mantraが終了する前にコールされます。

filterOutputAssets()

レンダリングが完了した後にコールされ、この関数にはレンダリング中に生成されるアセットのリストを渡します。それらのアセットは、以下の形式のリストで渡します:

[
    # Asset 1
    [assetname (str),
        [
            # そのアセットに関連したファイルのリスト
            [file (str), filetype (int)],
            [file (str), filetype (int)],
            ...
        ]
    ],
    # Asset 2
    [assetname (str),
        ...
    ],
    ...
]

<assetname> - アセット名 <file> - ファイルのパス <filetype> - ファイルのタイプ: 0-画像, 1-テクスチャ, 2-ジオメトリ, 3-シャドウマップ, 4-フォトンマップ, 5-環境マップ

import os

def filterOutputAssets(assets):
    # アセットをForeachします
    for a in assets:
        print 'Processing asset: \''+a[0]+'\''
        # アセット内のファイルをForeachします
        for f in a[1]:
            filename = f[0]
            filetype = f[1]
            filebase = os.path.splitext(filename)[0]
            # テクスチャをPNGフォーマットに変換します
            if filetype == 1:
                print 'Processing texture: \''+filename+'\''
                os.system('iconvert '+filename+' '+filebase+'.png')
            # ジオメトリをOBJフォーマットに変換します
            elif filetype == 2:
                print 'Processing geometry: \''+filename+'\''
                os.system('gconvert '+filename+' '+filebase+'.obj')

filterError(level, message, prefix)

Mantraがエラー、警告、Infoメッセージを出力した時にキャンセルされます。levelはメッセージの詳細レベル(エラーは0)、messageはメッセージ、prefixは通常では'mantra: 'プリフィックスです。 このメソッドは、そのエラーが処理された場合にTrueを、Mantraにそのエラーメッセージを正常に処理させているならFalseを返します。

filterTexture(operation, filename)

Mantraがテクスチャマップの問題に遭遇した時にコールされます。現在のところ、operationsは以下のどれかです:

  • missing – テクスチャが見つかりませんでした。

  • convert – テクスチャが.ratフォーマットでなかったので、内部的に変換します。

シンプルなフィルターのサンプル

#
# 単純なサンプルフィルター
#

import sys, mantra

Verbose = False

# モジュールの初期化中に引数を処理します。

for arg in sys.argv[1:]:
    if arg == '-v':
        Verbose = True

# すべてのオブジェクトのSurfaceシェーダを変更するためのコールバック。

def filterInstance():
    if Verbose:
        print 'Filtering:', mantra.property('object:name')

    mantra.setproperty('object:surface', 'plastic diff 1 0 0'.split())

    catstr = mantra.property('object:categories')[0]
    categories = catstr.split(', ')
    for c in categories:
        if c == 'pass1':
            mantra.setproperty('object:renderable', 0)

        elif c == 'pass2':
            mantra.setproperty('object:surface', 'matte')
            mantra.setproperty('object:overridedetail', 1)

ディープカメラ/シャドウマップのファイル名の変更

よくある質問は、Pythonがフィルタリングしている時のディープカメラ/シャドウマップを変更する方法です。 Mantraでは、ディープカメラファイルの名前がdeepresolverプロパティの一部になっています。このプロパティには、Deep Resolverに渡される引数すべてとそのファイル名が含まれております。 このサンプルは、既存のDeep Resolverステートメントを見つけて、新しいファイル名を使用するように引数を変更します。

def filterCamera():
    # 既存のdeepresolver引数を取得します
    deepresolver = mantra.property("image:deepresolver")
    if deepresolver:
        # 引数のコピーを作成します
        args = list(deepresolver)

        # リスト内のfilename引数の位置を探します
        # ("old_filename"を変更したいファイル名に置換します)
        i = args.index("old_filename") + 1
        # ファイル名を変更する
        args[i] = "new_filename"

        # 新しいリストをプロパティ値として設定します
        mantra.setproperty("image:deepresolver", args)

タイルの完了

renderer:tilecallbackプロパティを使って、各タイルが完了した後にMantraが実行するPythonスクリプト(とオプションの引数)を指定することができます。

Pythonフィルターとは違い、スクリプトは1つのみ指定できます(コマンドはセミコロンで分けることはできません)。スクリプトではMantraがコールする関数を定義しません。代わりに、Mantraは各タイルが完了する度に、全体のスクリプトを実行します。タイルスクリプトはmantra.setproperty()をコールすることができません。

いくつかの追加プロパティは統計を収集/表示するのに役に立つタイルコールバックで利用可能です。

  • tile:ntiles – 画像内のタイルの合計数。

  • tile:ncomplete – これまでに完了したタイルの数。

  • tile:laptime – 最後のタイルをレンダリングするのにかかった秒数。

  • tile:totaltime – レンダリングが開始してからのレンダリングの合計の秒数。これにはシーンの読み込みの時間は含まれていなくて、むしろ最初のタイルのレンダリングが始まってからの時間が定義されています。

  • tile:coords – タイル境界ボックス(ピクセル単位で)。

  • tile:memory – Mantraで使われたRAMの総量。

import sys,mantra

tile = mantra.property('tile:ncomplete')[0]
if tile == 1:
    # これは画像内でレンダリングされる1番目のタイルです。

    print mantra.property('renderer:name')
    ntiles = mantra.property('tile:ntiles')[0]
    prev_pct = -1
    lap = 0
    lsum = 0

lap += mantra.property('tile:laptime')[0]
pct = tile * 100 / ntiles

if pct != prev_pct:
    mem = mantra.property('tile:memory')[0]
    total = mantra.property('tile:totaltime')[0]
    fpct = float(tile)/float(ntiles) # Percent complete
    prev_pct = pct

    print('%03d%% Complete - Laptime %g/%g - ETA %g seconds\n' %
            (pct, lap, total, total/fpct))

    lap = 0         # lapカウンタをリセットします。
See also

レンダリング

Mantraユーザガイド

基本

ライティング

次のステップ

導師レベル

他のレンダラー