見出し画像

Render Setup 備忘録 ~スクリプトからレンダーレイヤーを組みオーバーライドする~

複雑に使うと壊れやすいなど問題のあったMayaの旧レンダーレイヤーはMaya 2016 Extention2(2016.5)で「Render Setup」という仕組みに刷新されました。
これまでのレンダリングに関する設定を行う「Render Setting」はそのままなので、「Render Setting」「Render Setup」と混同しやすい名前のが併在しているのはご愛敬です。

画像4

▲左がRender Setting。右がRender Setup

(新)レンダーレイヤーでは、レンダーレイヤーに含むオブジェクトを管理する「コレクション」、上書きする内容を管理する「オーバーライド」などが内部的にノード化され、それらの設定をスタックベースのUIで行なえます。
というUIの刷新もありがたいのですが、加えて嬉しいのがそれらをjsonで出力&流用できることと、スクリプトから作業するためのAPIが整理されたことです。

本稿は、このAPIについてレンダーレイヤー構築~オーバーライドするあたりまでの備忘録です。

承前

調べるとすぐ出てくる記事は公式のこちらです。

しかしオーバーライドには触れられていないのが玉に瑕。。。というところを本稿ではフォローしたいと思います。(そこまでは概ね同内容かと思います)

また、これは前提として頭に入れておきたいのですが、APIで行なった操作はリアルタイムにビューポートに反映されないことがあります。render setup のUIにはすぐ反映されますが。

レンダーレイヤーを切り替えたときに処理が走るので仕方なしといったところでしょうか(走らせるコマンドもあると思いますが調べてません)。必要に応じてレンダーレイヤーを切り替えてみてください。

APIを読み込む

上記記事の冒頭ではこのようになっています。

import maya.app.renderSetup.model.override as override
import maya.app.renderSetup.model.selector as selector
import maya.app.renderSetup.model.collection as collection
import maya.app.renderSetup.model.renderLayer as renderLayer
import maya.app.renderSetup.model.renderSetup as renderSetup
import maya.cmds as cmds

rs = renderSetup.instance()   

でも全部を読む必要はなく、 renderSetup だけ読んでいれば多くの場合いけると思います。

from pymel import core as pm
import maya.app.renderSetup.model.renderSetup as renderSetup

rs = renderSetup.instance()

レンダーレイヤーを作る

Render Setupで扱うノードの「最上位」要素が「レンダーレイヤー」です。まずはこれを作り、この中にオブジェクトを登録したりなんやかんやします。
これを作らなければ始まらない感じです。

rl = rs.createRenderLayer( 'layer_name' )

createRenderLayer メソッドで作ります。作られたレンダーレイヤーはこのあとも使っていくので、出力結果を受け取っておくのが大事です。

◆キャラごとにレンダーレイヤーを作る

簡単な実例として、シーン内のキャラごとにレンダーレイヤーを作ることを考えてみます。
「シーンに読み込まれているキャラ」は、ここではネームスペースからリストをつくることにします。リファレンスノードから洗ってもいいと思います。

ns_list = pm.namespaceInfo(lon=True)
ns_list.remove('UI')
ns_list.remove('shared')

for ns in ns_list:
   rl = rs.createRenderLayer( ns+'_rl' )

これで、見つかったネームスペース分だけレンダーレイヤーが自動で作られます。

コレクションを作る

レンダーレイヤーにオブジェクトを登録するには「コレクション」ノードを作成します。
エクスプレッションでシーン内のオブジェクトを読んでくれるほか、個別のオブジェクトを指定して登録することができます。

my_coll = rl.createCollection( 'collection_name' )

レンダーレイヤーオブジェクトに用意されている、createCollection メソッドで作ります。ここでも同様に結果を受け取っておきましょう。

オブジェクトを登録するためのエクスプレッションは、このようにして入力します。

my_coll.getSelector().setPattern( 'some_namespace:*' )

エクスプレッションの書き方については、主にこの辺り▼をご参考ください。

ネームスペース:*」という書き方で、ネームスペース以下の全部のオブジェクトを動的に登録できます。これで事足りることも多いと思います。

このほか、「ネームスペース:グループノード*」でそのグループ以下の全オブジェクトが対象になります。複数の条件をつなぐときは「;」です。「ネームスペースA:グループノード*; ネームスペースB:グループノード*; ネームスペースC:グループノード*; ...」みたいな。

またsetPatternでエクスプレッションを渡すのではなく、その下の欄に個別にオブジェクトを登録する、つまり静的にコレクションに登録する場合は setStaticSelection を使います。

my_coll.getSelector().setStaticSelection( object_list_str )

ただ、「オブジェクト名を改行で区切った文字列」を渡さねばならないので、ちょっとアナログな感じがします。

object_list_str = '\n'.join( [x.name() for x in obj_list] )
coll.getSelector().setStaticSelection( object_list_str )

こういうイメージでしょうか。本稿ではこちらは扱いません。

◆キャラごとにレンダーレイヤーを作り、コレクションも作る

ns_list = pm.namespaceInfo(lon=True)
ns_list.remove('UI')
ns_list.remove('shared')

for ns in ns_list:
   rl = rs.createRenderLayer( ns+'_rl' )
   mdl_coll = rl.createCollection( ns+"_mdl_coll" )
   mdl_coll.getSelector().setPattern( ns+'::geo_grp*' )

こんな感じになるんじゃなかろうか。映ってほしいジオメトリがgeo_grpというノード以下にまとめてある、という想定です。

シェーダーオーバーライド

コレクションを作れたら、オーバーライドを設定していきます。これを使って「このレンダーレイヤー内限定で有効な設定」「このレンダーレイヤー内ではこのマテリアルで上書き」といった設定を行います。Render Setupの真骨頂です。

画像2

スクリプトでオーバーライドを行う場合、createOverride というメソッドが用意されているのでそれを使います。オーバーライドのノード名と種類を渡すことでいろいろなオーバーライドが行なえます。

shd_ov = my_coll.createOverride( 'override_name','shaderOverride' )

'shaderOverride' を渡すとシェーダーオーバライドノードが作られますが、ここに渡すノード種はRender Setup プラグインに含まれるオーバーライドノードが(多分全部)使えると思います。

▲左のウィンドウをよく見ると、意外とたくさんあります

シェーディングエンジン・コレクション

コレクションにシェーダーオーバーライドを実行すると、コレクションとオーバーライドの間に自動的にもうひとつコレクションが作られます
この勝手に作られるコレクションは、よく見るとCollection Filtersが「Shading engines」になっていることが分かります(ちなみに普通に作ったコレクションの方は「Transforms」になってる)。

画像1

このコレクションにシェーディングエンジンを登録すると、それに関連するシェーダーがオーバーライドノードでオーバーライドされる、という関係になっています。
なので、こちらもエクスプレッションを入力してあげる必要があります。

shd_ov.parent().getSelector().setPattern( 'blinn1SG' )

オーバーライドから見て親の位置になるコレクションなので、 parent で取得できます。あとは既にやったのと同じ方法でエクスプレッションを書いてあげます(ここではラフに ~SG と直書きしています)。
ちなみに、これをやらない場合はエクスプレッションは「*」と入力されており、すべてのシェーダーが上書きされます。

また、シェーダーオーバーライドではこのように「シェーディングエンジン指定用のコレクションが自動で作られる」という挙動ですが、マテリアルオーバーライドにはこれはありません。

オーバーライドしたいシェーダーをセット

shd_ov.setShader( 'blinn2' )

オーバーライドしたいノード名を setShader メソッドに渡してあげれば登録できます。

◆キャラごとにレンダーレイヤーを作り、別キャラで抜かれるようマットを設定する

最後に簡単な実例です。
キャラごとにレンダーレイヤーを作ったら、その中にコレクションを二つ作り、片方に「画が出てほしいキャラ」、片方に「それ以外のキャラ」を入れます。前者は普通に画を出す用で、後者はそれを抜くためにオーバーライドをしたいと思います。

ns_list = pm.namespaceInfo(lon=True)
ns_list.remove('UI')
ns_list.remove('shared')

mat_mtl = '(事前にマット用シェーダー作っておいてください)'

for ns in ns_list:
   rl = rs.createRenderLayer( ns+'_rl' )
   mdl_coll = rl.createCollection( ns+"_mdl_coll" )
   mdl_coll.getSelector().setPattern( ns+'::geo_grp*' )
   # 特定シェーダをオーバーライドする例
   shd_ov = mdl_coll.createOverride( 'override_name','shaderOverride' )
   shd_ov.parent().getSelector().setPattern( 'blinn1SG' )
   shd_ov.setShader( 'blinn2' )

   # ほかのキャラで抜く用コレクション+オーバーライド
   mat_coll = rl.createCollection( ns+"_mat" )
   mat_pattern = ':*; '.join([x for x in ns_list if x != ns]) +':*;'
   mat_coll.getSelector().setPattern( mat_pattern )
   mat_ov = mat_coll.createOverride(ns+'_mat_ov',"shaderOverride")
   mat_ov.setShader( mat_mtl )

マット用コレクションには、そのキャラ「以外」をまとめて登録したいので、ネームスペースリストをforでまわして、いまターゲットにしているネームスペース「以外」を連結しました(下から4行目)
joinでは ':*; ' は間に挟まるだけで末尾にはつかないので、追って足しています。

おわりに

ここではシェーダーオーバーライドのみ言及しましたが、ほかのオーバーライド(たとえばアトリビュート値を上書きするための absolute override など)も探ってみてください。

冒頭の公式記事には、jsonを読み書きするためのスクリプトも載っています。json出力してもよし、本稿のように動的にごりごり作ってもよし、です。

おまけ 〜取得する〜

作ったレンダーレイヤーは getRenderLayers で取得できます。また、レンダーレイヤー以下の構造は getChildren で取得できます。

for rl in rs.getRenderLayers():
   print(rl.name())
   for child in rl.getChildren():
       print('\t'+child.name())

…みたいな感じで再帰的にやっていくと全部受け取れると思います。

***

続きを書きました▼


この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
note.user.nickname || note.user.urlname

記事の感想をマシュマロなどでいただけるとよろこびます🙌 https://marshmallow-qa.com/it_ks (サポートいただけるとさらによろこび投稿頻度が増えます🙌🙌)

技術本を作るサークル、Circke Qtのksです。 BOOTHにて既刊お求めいただけます > https://circleqt.booth.pm  普段はフリーランスCG屋、テクニカルライター、講師業などしています。

こちらでもピックアップされています

CG
CG
  • 22本

CG制作とその周辺情報などの記事をこちらにまとめています。

コメントを投稿するには、 ログイン または 会員登録 をする必要があります。