株式会社デジタル・フロンティア-Digital Frontier

Header

Main

  • TOP
  • DF TALK
  • NukeでのPositionPass有効活用法

NukeでのPositionPass有効活用法

2016/11/14

Tag: ,

前回の記事からだいぶ経ってしまいました、開発山口です。
今回はPosition Passを利用したDepth Passの作成方法を紹介したいと思います。
使い古されたネタかもしれませんがお付き合いください。

始めに

記事内の説明で使用しているNukeのシーンファイルですが、コピペしてシーン内に再現できるようにテキストを
用意しました。”expand source”をクリックしていただければ出てきますので記事と合わせて見てください。
※1度開いてしまうと閉じられないみたいなので、コピペが終わったらリロードしてください。
またNuke7.0以上のバージョンでお試しください。

BackdropNode {
 inputs 0
 name BackdropNode1
 tile_color 0x8e388e00
 label "Hight Depth"
 note_font_size 42
 xpos -1456
 ypos -3373
 bdwidth 243
 bdheight 456
}
BackdropNode {
 inputs 0
 name BackdropNode2
 tile_color 0x8e388e00
 label "Depth 02"
 note_font_size 42
 xpos -638
 ypos -3374
 bdwidth 345
 bdheight 455
}
BackdropNode {
 inputs 0
 name BackdropNode3
 tile_color 0x8e388e00
 label "Depth 01"
 note_font_size 42
 xpos -1183
 ypos -3373
 bdwidth 248
 bdheight 455
}
BackdropNode {
 inputs 0
 name BackdropNode4
 tile_color 0x8e388e00
 label "Point Depth"
 note_font_size 42
 xpos -902
 ypos -3373
 bdwidth 243
 bdheight 456
}
BackdropNode {
 inputs 0
 name BackdropNode5
 label "Render Position Map"
 note_font_size 42
 xpos -757
 ypos -3905
 bdwidth 451
 bdheight 337
}
BackdropNode {
 inputs 0
 name BackdropNode6
 tile_color 0x88aa88ff
 label Relight
 note_font_size 48
 xpos -1846
 ypos -3372
 bdwidth 362
 bdheight 312
}
BackdropNode {
 inputs 0
 name BackdropNode7
 tile_color 0x88aa88ff
 label PositionToPoint
 note_font_size 48
 xpos -2218
 ypos -3372
 bdwidth 347
 bdheight 312
}
push $cut_paste_input
Axis2 {
 name Axis
 xpos -730
 ypos -3256
}
Camera2 {
 inputs 0
 rot_order XZY
 translate {-3.731961727 3.420248747 5.088853359}
 rotate {-22.1907843 -28.86123413 -2.391627877}
 focal 26.5
 haperture 26.5
 vaperture 13.2
 name renderCamera
 xpos -742
 ypos -3715
}
set Nf88a9c00 [stack 0]
Card2 {
 inputs 0
 translate {0 -1.057815808e-007 -2.420000076}
 rotate {-90 0 0}
 scaling {20 20 20}
 control_points {3 3 3 6

1 {-0.5 -0.5 0} 0 {0.1666666865 0 0} 0 {0 0 0} 0 {0 0.1666666865 0} 0 {0 0 0} 0 {0 0 0}
1 {0 -0.5 0} 0 {0.1666666716 0 0} 0 {-0.1666666716 0 0} 0 {0 0.1666666865 0} 0 {0 0 0} 0 {0.5 0 0}
1 {0.5 -0.5 0} 0 {0 0 0} 0 {-0.1666666865 0 0} 0 {0 0.1666666865 0} 0 {0 0 0} 0 {1 0 0}
1 {-0.5 0 0} 0 {0.1666666865 0 0} 0 {0 0 0} 0 {0 0.1666666716 0} 0 {0 -0.1666666716 0} 0 {0 0.5 0}
1 {0 0 0} 0 {0.1666666716 0 0} 0 {-0.1666666716 0 0} 0 {0 0.1666666716 0} 0 {0 -0.1666666716 0} 0 {0.5 0.5 0}
1 {0.5 0 0} 0 {0 0 0} 0 {-0.1666666865 0 0} 0 {0 0.1666666716 0} 0 {0 -0.1666666716 0} 0 {1 0.5 0}
1 {-0.5 0.5 0} 0 {0.1666666865 0 0} 0 {0 0 0} 0 {0 0 0} 0 {0 -0.1666666865 0} 0 {0 1 0}
1 {0 0.5 0} 0 {0.1666666716 0 0} 0 {-0.1666666716 0 0} 0 {0 0 0} 0 {0 -0.1666666865 0} 0 {0.5 1 0}
1 {0.5 0.5 0} 0 {0 0 0} 0 {-0.1666666865 0 0} 0 {0 0 0} 0 {0 -0.1666666865 0} 0 {1 1 0} }
 name Card
 xpos -395
 ypos -3804
}
Cube {
 inputs 0
 cube {-6.119999886 -1.220000029 -1.379999995 -3.900000095 1.019999981 -3.319999933}
 translate {4.239999771 1.210000038 -0.3600000143}
 name Cube
 xpos -395
 ypos -3769
}
Sphere {
 inputs 0
 translate {-2.170000076 0.9399999976 0}
 name Sphere
 xpos -395
 ypos -3729
}
Cylinder {
 inputs 0
 close_top true
 close_bottom true
 translate {0.8500000238 0.9599999785 -0.1000000015}
 name Cylinder
 xpos -395
 ypos -3690
}
Scene {
 inputs 4
 name Scene
 xpos -489
 ypos -3769
}
Constant {
 inputs 0
 channels rgb
 format "640 480 0 0 640 480 1 PC_Video"
 name Constant
 xpos -592
 ypos -3821
}
add_layer {position position.red position.green position.blue position.alpha}
add_layer {normal normal.red normal.green normal.blue normal.alpha}
ScanlineRender {
 inputs 3
 output_shader_vectors true
 P_channel position
 N_channel normal
 name ScanlineRender
 xpos -592
 ypos -3718
 postage_stamp true
}
Shuffle {
 in position
 out rgb
 name Shuffle1
 xpos -592
 ypos -3646
 postage_stamp true
}
set N88b9cc00 [stack 0]
PostageStamp {
 name PostageStamp1
 xpos -1383
 ypos -3278
 hide_input true
 postage_stamp true
}
Shuffle {
 red green
 blue green
 name Shuffle
 xpos -1383
 ypos -3165
}
Grade {
 whitepoint 2
 name set_range_hightDepth
 xpos -1383
 ypos -3101
}
Premult {
 name Premult4
 xpos -1383
 ypos -3022
 postage_stamp true
}
push $N88b9cc00
PostageStamp {
 name PostageStamp3
 xpos -503
 ypos -3288
 hide_input true
 postage_stamp true
}
set N1229e000 [stack 0]
Expression {
 expr0 r-renderCamera.translate.x
 expr1 g-renderCamera.translate.y
 expr2 b-renderCamera.translate.z
 name make_pixcelVector
 xpos -601
 ypos -3178
}
push $N1229e000
Expression {
 expr0 -renderCamera.world_matrix.2
 expr1 -renderCamera.world_matrix.6
 expr2 -renderCamera.world_matrix.10
 name make_cameraVector
 xpos -405
 ypos -3177
}
MergeExpression {
 inputs 2
 temp_name0 DotAB
 temp_expr0 (A.r*B.r+A.g*B.g+A.b*B.b)
 temp_name1 vecA_length
 temp_expr1 sqrt(A.r*A.r+A.g*A.g+A.b*A.b)
 temp_name2 vecB_length
 temp_expr2 sqrt(B.r*B.r+B.g*B.g+B.b*B.b)
 temp_name3 angle
 temp_expr3 acos(DotAB/(vecA_length*vecB_length))
 channel0 rgb
 expr0 cos(angle)*vecA_length
 name make_distance
 xpos -502
 ypos -3113
}
Grade {
 whitepoint 20
 name set_range_depth2
 xpos -502
 ypos -3063
}
Premult {
 name Premult1
 xpos -502
 ypos -3003
 postage_stamp true
}
push $N88b9cc00
PostageStamp {
 name PostageStamp2
 xpos -1099
 ypos -3277
 hide_input true
 postage_stamp true
}
Expression {
 temp_name0 x
 temp_expr0 r-renderCamera.translate.x
 temp_name1 y
 temp_expr1 g-renderCamera.translate.y
 temp_name2 z
 temp_expr2 b-renderCamera.translate.z
 temp_name3 length
 temp_expr3 sqrt(x*x+y*y+z*z)
 channel0 rgb
 expr0 length
 channel1 {-rgba.red -rgba.green -rgba.blue none}
 channel2 {-rgba.red -rgba.green -rgba.blue none}
 name make_pixcelVector1
 xpos -1099
 ypos -3167
}
Grade {
 whitepoint 20
 name set_range_depth1
 xpos -1099
 ypos -3082
}
Premult {
 name Premult3
 xpos -1099
 ypos -3011
 postage_stamp true
}
push $N88b9cc00
PostageStamp {
 name PostageStamp4
 xpos -829
 ypos -3279
 hide_input true
 postage_stamp true
}
Expression {
 temp_name0 x
 temp_expr0 r-Axis.translate.x
 temp_name1 y
 temp_expr1 g-Axis.translate.y
 temp_name2 z
 temp_expr2 b-Axis.translate.z
 temp_name3 length
 temp_expr3 sqrt(x*x+y*y+z*z)
 channel0 rgb
 expr0 length
 channel1 {-rgba.red -rgba.green -rgba.blue none}
 channel2 {-rgba.red -rgba.green -rgba.blue none}
 name make_pixcelVector2
 xpos -829
 ypos -3160
}
Grade {
 blackpoint 3
 whitepoint 0
 name set_range_pointDepth
 xpos -828
 ypos -3065
}
Premult {
 name Premult2
 xpos -828
 ypos -3003
 postage_stamp true
}
push $N88b9cc00
PostageStamp {
 name PostageStamp6
 xpos -2121
 ypos -3278
 hide_input true
 postage_stamp true
}
CheckerBoard2 {
 inputs 0
 name CheckerBoard1
 xpos -1998
 ypos -3222
}
PositionToPoints2 {
 inputs 2
 display textured
 render_mode textured
 cast_shadow false
 receive_shadow false
 P_channel rgb
 detail 0.255
 pointSize 2.1
 name PositionToPoints1
 xpos -2121
 ypos -3117
}
BasicMaterial {
 inputs 0
 name BasicMaterial1
 xpos -1824
 ypos -3185
}
push $Nf88a9c00
Dot {
 name Dot2
 xpos -1524
 ypos -3691
}
Dot {
 name Dot1
 xpos -1524
 ypos -3158
}
Light2 {
 inputs 0
 intensity 2
 translate {0.5 5.639999866 4.559999943}
 depthmap_slope_bias 0.01
 name Light1
 xpos -1726
 ypos -3206
}
push $N88b9cc00
PostageStamp {
 name PostageStamp5
 xpos -1653
 ypos -3281
 hide_input true
 postage_stamp true
}
ReLight {
 inputs 4
 normal normal
 position rgb
 name ReLight1
 xpos -1653
 ypos -3099
}

nukescene

Position Passとは

Position Passとは、各PixelのRGBに対し、オブジェクトのXYZ値を格納したPassです。

positionpass

使い方は様々で、例えばNormal Passと組み合わせることで、影無しではありますが
簡易的なライティングをすることも可能です。

relight

PositionToPointsノードを使用することで、各Pixelの位置を3D空間上でどこにあるか
調べることもできます。

positiontopoints

このように様々な使用用途がある素材ですが、今回はこれを利用してNuke上でDepthを作成する
方法を紹介したいと思います。

Mayaからの出力

まずこのPassを作成する所から始めたいと思います。
Position Passはレンダラーで標準でサポートされているものも有りますが、今回は既存の
ノードを使用して出力してみたいと思います。
使用するレンダラーはmentalrayです

といっても、とても簡単でSurfaceShaderのOutColorにsamplerInfoノードのPoint Worldをつなぐだけです。
positionpassshader

あとはこれでレンダリングするだけでPosition Passが出力できます。
この際に気をつけてほしいのが出力設定で、必ず32bit floatで出力してください。

mentalraysettings

なぜこの設定がなぜこれでなければいけないのかは、次回あたりにでも記事にしたいと思います。
レンダリング結果をNukeで開き、各サーフェイスの値に1以上、0以下の値が入っていれば成功です。

高さDepth

hightdepthimage

では早速Depthを作成していきます。
まず高さDepthです。これはとても簡単です。

そもそもPosition PassにはGチャンネルに高さ情報が入っているので、これの
レンジを変えてあげるだけで簡単に作成できます。

ShuffleノードでGチャンネルだけ取り出し、GradeノードのBlackPointとWhitePointに
値を入れてあげるだけです。

hightdepth

奥行きDepth01

depth01image

次はカメラからのDepth素材です。
カメラからのDepth素材には円形のDepthと線形のDepthの2つがあります。

depthtype

まず、簡単なほうの円形のDepthを紹介します。

これも非常に簡単で各Pixelの位置情報からカメラの位置を引き算し、そのベクトルの距離を求め
レンジを調節してあげることで求めることができます。

depth01

任意のポジションからのDepth

positiondepthimage

これは奥行きDepth01の応用です。
カメラのポジションを任意のポジションに変えてあげるだけです。
Axisノードを使用して、それのポジション情報を使用すれば3D空間上で位置決めが楽になります。

positiondepth

奥行きDepth02

depth02image

最後に線形のDepthです。
数学の知識が無いとなかなか難しいですがチャレンジしてみてください。

下図の緑のベクトルの長さで、これを求めるにはその他にカメラから各Pixelまでのベクトルと
カメラからの視線ベクトルが必要です。

vector

この2つのベクトルを利用して、ベクトル間の角度を求め
三角関数のcosineを使用すれば緑のベクトルを求めることが出来ます。
thetacosine-1

では実際にNukeでの操作を見て行きたいと思います

2つのベクトルを作成

まず2つのベクトルを作成します。

1つめがカメラから各Pixelに向かうベクトルで、各Pixelの値からカメラのポジションを引き算することで求められます。
pixelvectornuke

2つめがカメラの視線ベクトルです。

カメラの視線ベクトルはアトリビュートのWorld Matrixの部分から作成することができます。
そもそもカメラベクトルは(0, 0, -1)とZがマイナスなので、視線ベクトルとしてはマイナスを掛けてあげる必要があります。
式はMatrix × Camera Vectorです。

ちょっと難しく思うかも知れませんが、下図のMatrixの値に-1を乗算してあげることで作成できます。

matrix

エクスプレッションにはこのように書きます。
※ここではあえてカラー値にしていますが、そのまま計算式として入れてしまってもいいです。

cameravectornuke

マイナスに変換したのは2つベクトルの方向を合わせるためです。
1つ目のベクトルの計算を”カメラのポジション”から”各Pixelの値”を引くように
計算式を変更しても最終結果は同じになります。

2つのベクトルのなす角を求める

2つのベクトルの間の角度は下記の計算式で求めることが出来ます。

gettheta

これをNukeのExpressionノード表現すると下図のようになります。

getangle

ベクトルの長さを求める

上の式から求められた角度と三角関数のcosine、カメラから各Pixelに向かうベクトルの長さの3つを
使用して、最終的なDepth値を求めます。

vectordistance

こんな書き方も

実は下記のようにacosとcosは打ち消すことが出来ます。

vectordistance

処理の流れとしては上の方がわかりやすいですが、わかってしまえば下の方のが計算処理が
速くなるので状況に応じて使い分けてください。

レンジ(Near,Far)の調整

このままでは、単純に3D上での距離が入っているだけですので
gradeノードを使用して、レンジ(Near,Far設定)を設定します

rangesettings

rangesettingsimage

以上で完成です。

Position Passは工夫すれば色んな使い方ができて、なかなか面白い素材です。
カメラの情報等別途必要になる物も有りますが、頑張って素材のHeaderに埋め込むなど
してしまえば、カメラの情報が無くても何とかなったりします。

ぜひ、皆さんも活用してみてください。


※免責事項※
本記事内で公開している全ての手法・コードの有用性、安全性について、当方は一切の保証を与えるものではありません。
これらのコードを使用したことによって引き起こる直接的、間接的な損害に対し、当方は一切責任を負うものではありません。
自己責任でご使用ください。

Pocket

コメント

😉

1 thought on “NukeでのPositionPass有効活用法”

  1. とんとこ より:

    😉

コメントフォーム

コメントは承認制ですので、即時に反映されません。ご了承ください。

*