Houdini の Pre-Render Script を使ってみる 

Houdini の出力系のROPノードのパラメータ欄にある Pre-Render Script というものが以前から気になっていたのですが、最近 Houdini での Python を覚えてきたので利用してみました。
その時、少し躓いた箇所もあったので、記事にしました。

#Pre-Render Script って何？
Pre-Render Script とは、文字通りレンダリング前に実行したい処理を書いたスクリプトのことです。
出力系のROPノードには、それを自動的に実行するための仕組みが備わっていて、レンダリングのほかベイクやFBX出力でも使うことが可能です。
映像系の方は普通に使っている機能なのかもしません。

例えばBake Texture ROP を見てみましょう。
outputs コンテキストに移動し、Tab メニューから Bake Texture を選択してノードを作成、
![2019-01-16_1503.png](https://qiita-image-store.s3.amazonaws.com/0/314518/ef911992-2bef-1f08-1d5b-c4af734ac67c.png)
パラメータ欄の Advanced>Scripts タブの中に
「Pre-Render Script」というパラメータを確認できます。
![2019-01-16_1444.png](https://qiita-image-store.s3.amazonaws.com/0/314518/d6be8569-aae0-7cfd-3684-a6ea00c7466d.png)
ここに処理を書いたスクリプトを指定することでレンダリング前にそのスクリプトが走るようになります。
今回はさわりませんが同列に Pre-Frame Script や Post-Render Script なども並んでますね。

#スクリプトの準備
では早速使ってみたいと思います。
まず、スクリプトを準備します。
外部のエディタでスクリプトを書きファイルとして保存します。
Hscript か Python を使うことが可能ですが、今回は Python を使いました。
今回、サンプルファイルはないのですが、例としてスクリプトを準備しました。

テキストエディタなどで下記を記述し pre_render_script.py として適当な場所に保存します。

```python
import hou

#ハイポリメッシュのレンダーフラグをオン
modelHi = hou.node('/obj/hi/output1')
modelHi.setRenderFlag(True)
modelHi.setDisplayFlag(True)

#ローポリメッシュのレンダーフラグをオン
modelLow = hou.node('/obj/low/output1')
modelLow.setRenderFlag(True)
modelLow.setDisplayFlag(True)
```

このスクリプトは指定したノードのフラグをオンにするだけのスクリプトで、
Bake Texture ROP によるテクスチャベイク時に実行することを想定したものになります。
（Python自体の詳しい解説はここでは割愛します。多くの情報がすでにWebにありますので。）

Bake Texture ROP はハイポリからローポリへのテクスチャベイクをするオペレータですが、ベイク対象として指定できるのは Scene レベルのノード（geometry node など）となり、SOP を指定することができません。
なのでベイクする前に、geometry内の対象となる SOP のレンダーフラグを手動でオンにしておく必要があるのですが、これがまた、作業してベイクというサイクルを繰り返していると、しばしばオンにし忘れてベイクをミスるということがよくあるのです。
そのミスを防ぐためのスクリプトとなり、ハイポリとローポリのSOPのレンダーフラグと表示フラグをオンにするだけのスクリプトです。

#スクリプトの指定
スクリプトファイルの準備ができたら、あとはそのファイルを指定すればオッケー…
といきたいところですが、ここでPythonでスクリプトを書いている場合に
ひっかかりポイントがあります。

まず、矢印のアイコンからスクリプトのファイルを選択すると
パスが表示されるのはテクスチャ画像を使うときなどと同じです。
![2019-01-19_1222.png](https://qiita-image-store.s3.amazonaws.com/0/314518/0cd56975-831e-819f-3f30-8f4a9490bcd7.png)
が、
Houdiniで一般的に外部ファイル指定するこの書き方がPythonスクリプトの場合
この状態でRenderボタンをおすと、Pythonのエラーになってしまいます。。

エラーを回避するには

```
$HIP/scripts/pre_render_script.py
```
を以下のように変更します。

```
execfile('$HIP/scripts/pre_render_script.py')
```

これで、きちんとスクリプトが動いてくれます。
なかなか罠のような仕組みになってますが、このへんは常識なんでしょうか…？
これを知るまで、Python初心者である自分は、まずScriptの中を一生懸命探しちゃいました。。
Pythonのスクリプトをファイルで指定するときは忘れないようにしたいです。

以上、Pre-Render Script についての解説でした。


#ついでに余談
ここから先は今回の記事とは関係ない余談です。

ところで、HighポリメッシュからLowポリメッシュへのベイクは
SOP にあるGame Dev Simple Baker がシンプルで使いやすいです。
HighポリメッシュとLowポリメッシュを直接つなぐだけなので
フラグを設定し忘れて起こるようなミスもありません。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314518/f1002d7e-2239-4550-e0f0-2bd9cf6602fb.png)

この Simple Baker 表に出ている設定をどんなにいじっても
きれいにレンダリングしてくれません。
Sample数が足りていないような少しノイジーなBake結果になってしまいます。

これを改善するには
Game Dev Simple Baker の中にある
![2019-01-19_1259.png](https://qiita-image-store.s3.amazonaws.com/0/314518/1ed10e29-ab8c-a069-cf5d-3b5b15091959.png)
ropnet1 のさらに中の
![2019-01-19_1301.png](https://qiita-image-store.s3.amazonaws.com/0/314518/8ebbf76e-b89a-51fe-33b8-23e1d72c4a8b.png)
rop_games_baker のさらに中の
以下のノードの
![2019-01-19_13012.png](https://qiita-image-store.s3.amazonaws.com/0/314518/316b0eaa-2ea8-24f4-57b7-8e381215a57d.png)
Pixel Samples の値を上げる(下図)とよいです。
※レンダリング時間は伸びます
![image.png](https://qiita-image-store.s3.amazonaws.com/0/314518/2b113f54-7efb-b6a9-88da-b7bfe447ec2b.png)

以上、余談でした。

使用したバージョンはHoudini17.0.416、Game Dev 1.98 となります。