はじめに
最初から読む: 【OSL入門】MayaでArnoldのシェーダーを書く①
前回の記事: 【OSL入門】MayaでArnoldのシェーダーを書く④~closure~
前回の記事まではOSL を、色や closure を出力するのに使用していました。
この記事では、Maya の aiOslShader から float 値を出力し、Arnoldでディスプレイスメントとして使用し、レンダリング時にメッシュを変形させる手順を解説します。
UV に沿った波形と画像テクスチャの2例を作成し、形状ががたついたり欠けてしまう場合に必要な Subdivision と Bounds Padding の設定まで確認します。
OSL のコンパイルと aiOslShader への読み込み方法は第1回の記事を、テクスチャを使用する方法については第3回の記事を参照してください。
displacement とは
displacement は、シェーディングポイントを法線方向へ移動して、メッシュの表面に凹凸を作る仕組みです。
バンプやノーマルマップでも凹凸を表現できますが、こちらは基本的に法線を変えて陰影を作る方法なので、オブジェクトの輪郭は変わりません。

一方、displacement はレンダリング時にサーフェスの位置を移動するため、オブジェクトの輪郭や影にも凹凸が反映されます。

OSL で displacement を適用する手順

ディスプレイスメント値の出力
displacement に渡す値は、シンプルな float 型で作成できます。
まずは、UV の U 方向に波模様を作る以下のコードをコンパイルすると、aiOslShader に outDisplacement という出力アトリビュートが作成されます。
shader displacement_shader(
float frequency = 8.0,
float amplitude = 0.1,
output float outDisplacement = 0.0
){
float wave = sin(u * frequency * 6.28318530718);
outDisplacement = wave * amplitude;
}
接続
プリミティブの Sphere を作成し、 aiStandardSurface を割り当てます。
その aiStandardSurface の Shading Group の Displacement Shader に outDisplacement をつなぎます。

displacement の強さなどを調整できて便利なので、間に displacementShader を作成して挟むつなぎ方を推奨します。

レンダリングすると、単純な球体が displacement によって、波打ちます。

Subdivision の設定
ただし、このままだと、ポリゴンの細かさが足りず、角ばって見えたり表面が汚く見えます。
オブジェクトを選択し、Attribute Editor でその shape の Arnold タブの Subdivision タブの Type を catclark に変更します。
iterations を大きくするほど滑らかになりますが、レンダリング時に使用するメモリや計算時間が急激に増えるので、値を大きくしすぎないように注意してください。
輪郭の角張りが目立たなくなるまで、1ずつ値を大きくしてください。


frequency は波の繰り返し数、amplitude は凹凸の大きさです。
sin() の結果は-1.0から1.0の範囲で変化します。
そこへ amplitude を掛けることで、出力は -amplitude から amplitude の範囲になります。
6.28318530718 は円周率の2倍です。U 座標の0~1を sin() の1周期へ変換し、frequency の回数だけ繰り返しています。
Bounds Paddingの設定
Arnold は、レンダリングを効率化するためにオブジェクトが存在する範囲をあらかじめ見積もっています。
displacement によって、その範囲より外側までメッシュが移動すると、バウンディングボックスの形に、形状の一部が欠けてレンダリングされる場合があります。

その場合は Shape ノードの Arnold にある Bounds Padding を、想定する変位量に合わせて大きくします。
今回のコードでは outDisplacement が-amplitudeからamplitudeまで変化します。amplitude を1.0としている場合は、まず Bounds Padding も1.0以上を目安に設定します。

値を必要以上に大きくするとレンダリング効率が落ちるので注意してください。
欠けるはずなのに欠けてなかったり、正しく設定したのに形状の一部が削れたままの場合は、Arnold RenderView メニュー > Render > Update Full Scene (ctrl+U) で更新してください。
テクスチャをdisplacementに使用する
【OSL入門】MayaでArnoldのシェーダーを書く③~テクスチャ~で解説した関数 texture() と組み合わせることで、画像ファイルの明るさを displacement に使用することもできます。
shader texture_displacement_shader(
string fileName = "",
float amplitude = 0.1,
output float outDisplacement = 0.0
){
color texColor = texture(fileName, u, 1.0-v);
float height = luminance(texColor);
outDisplacement = (height - 0.5) * amplitude;
}
このコードはmeshのUV座標を使用しているため、UVが0~1の範囲に展開されていることを確認してください。

luminance() でテクスチャを1つの float 値へ変換しています。
テクスチャの値が0.5の場所を移動しない基準とし、暗い場所は内側、明るい場所は外側へ移動します。
このコードでは、テクスチャが0.0から1.0の範囲であれば、出力は-amplitudeの半分からamplitudeの半分までです。
まとめ
今回は、OSL で displacement を作成し、メッシュの表面に凹凸を作成しました。
- aiOslShader の float 出力を Shading Group の Displacement Shader または displacementShader の Displacement へ接続する。
- 細かな凹凸には Arnold の subdivision を使用する。
- 形状が欠ける場合は Bounds Padding を確認する。
- 画像やノイズを高さ情報として扱うこともできる。
次回に続きます。
次回の記事: 未公開



コメント