【OSL入門】MayaでArnoldのシェーダーを書く③~テクスチャ~

OSLコードとシェーダーノード、グレースケールの3D球体を並べた「OSL入門③」のアイキャッチ Tech

はじめに

最初から読む: 【OSL入門】MayaでArnoldのシェーダーを書く①

前回の記事: 【OSL入門】MayaでArnoldのシェーダーを書く②~標準関数とグローバル変数~

前回に引き続き、Maya の aiOslShader による OSL の使い方を解説していきます。

今回は、Maya の aiOslShader で画像テクスチャを読み込む方法を解説します。
texture() の基本、移動や繰り返しを、実行できる OSL コードと画像で確認します。

OSL シェーダーの作成・コンパイル手順については第1回、標準関数とグローバル変数については第2回を参照してください。

テクスチャの表示

OSL では、関数 texture() を使用することでテクスチャの色を取得できます。
引数として、ファイル名と、サンプリングするテクスチャの座標が必要です。

texture(ファイル名, U, V)

まず、ファイル名は入力から受け取ることができます。

shader texture_shader(
    string fileName = "",
    output color outColor = 0
){}

これをコンパイルすると、fileName というラベルの入力欄が現れます。

MayaのaiOslShaderをコンパイルし、Attribute EditorにfileName入力欄が追加された状態

例えば、D:/MayaProject/sourceimages/tex.png を読み込むには、fileName 欄へそのパスを入力します。

MayaのaiOslShaderのfileNameにテクスチャの絶対パスを入力した状態

テクスチャファイルが現在の Maya プロジェクトの sourceimages フォルダにある場合は、tex.png のようにファイル名だけでも読み込めます。

Mayaプロジェクトのsourceimagesにあるtex.pngをファイル名だけで指定した状態

UV 座標はグローバル変数 u, v で取得することができます。
ただし、テクスチャの原点は左上隅であることに注意してください。
そのままグローバル変数 v を渡すと上下が反転してしまうので、1.0-v を渡します。

texture(fileName, u, 1.0-v);

まとめると、以下のように、ファイル名をUIから入力として受け取り、texture 関数にファイル名、UV座標を渡した結果を outColor に代入することでテクスチャを表示することができます。

shader texture_shader(
    string fileName = "",
    output color outColor = 0
){
    outColor = texture(fileName, u, 1.0-v);
}
Maya ArnoldでOSLのtexture関数から読み込んだテクスチャをモデルに表示した結果

レンダリングした際に、カラーマネジメントの影響でテクスチャの色味がおかしくなることがあります。

Maya ArnoldでsRGBテクスチャの色がカラーマネジメントにより変化したレンダリング結果

詳しい解説は省きますが、sRGB 画像を Rendering Space (画像青枠)がACEScg のシーンに読み込みたい場合、以下のように sRGB → ACEScg に変換することで正しく表示されます。

shader texture_shader(
    string fileName = "",
    output color outColor = 0
){
    color tex = texture(fileName, u, 1.0 - v);
    outColor = transformc("sRGB", "ACEScg", tex);
}

Color Management が必要ない場合は、Enable Color Management のチェック(画像赤枠)を外すことでColor Managementが無効になり、色味が直ります。

MayaのColor Management設定にあるACEScgのRendering Spaceと有効化項目

テクスチャ操作

texture() によりサンプリングした texColor は単なる色データです。
したがって、通常の色として様々な計算を行うことができます。

サンプリングした色の操作例をいくつか示します。

RGB 値の分解

RGB 値を分解して R 値だけ取り出すことが可能です。

Maya ArnoldでテクスチャのR成分だけを赤色として出力した結果
shader texture_shader(
    string fileName = "",
    output color outColor = 0
){
    color texColor = texture(fileName, u, 1.0-v);
    float R = texColor[0];
    outColor = color(R, 0, 0);
}

テクスチャのカラー合成

複数のテクスチャを加算することができます。

Maya Arnoldで2枚のテクスチャをOSLにより加算合成した結果
shader texture_shader(
    string fileName1 = "",
    string fileName2 = "",
    output color outColor = 0
){
    color texColor1 = texture(fileName1, u, 1.0 - v);
    color texColor2 = texture(fileName2, u, 1.0 - v);
    outColor = texColor1 + texColor2;
}

もちろん計算式次第で乗算やスクリーン合成等、様々なカラー合成が可能です。

// 乗算の例
color multiplyColor = texColor1 * texColor2;  
// スクリーンの例
color screenColor = 1.0 - (1.0 - texColor1) * (1.0 - texColor2);

フレネルの合成

前回記事でフレネル風シェーダーを作成しましたが、テクスチャと組み合わせることも可能です。

Maya Arnoldでテクスチャにフレネル風のリム成分を加算した結果
shader texture_shader(
    string fileName = "",
    float rimPower = 1.0,
    output color outColor = 0
){
    float fresnel = clamp( dot(normalize(N), -normalize(I)), 0.0, 1.0 );
    float rim = pow(1.0 - fresnel, rimPower);

    outColor = texture(fileName, u, 1.0-v) + rim;
}

そのほかにも、ノーマルマップを読み込んだり、複数のテクスチャを切り替えたり、柔軟にテクスチャを扱うことが可能です。

テクスチャの移動

これまで見てきたように、グローバル変数 u, v を(v座標は反転して) texture() の第2、第3引数に渡すことで、シェーディングポイントの UV 座標に対応する箇所の色をテクスチャから取得(サンプリング)できます。

texture(fileName, u, 1.0-v);

この引数は必ずしも u, 1.0-v である必要はありません。
例えば0.6, 0.5とすることで、メッシュのUV座標に関わらず、テクスチャの左上から0.6, 0.5の位置の色がサンプリングされます。(右下が1.0, 1.0です。)

shader texture_shader(
    string fileName = "",
    output color outColor = 0
){
    outColor = texture(fileName, 0.6, 0.5);
}

texture() に渡す引数 u, v に offset 値を加算(減算)することで表示するテクスチャをずらすことができます。

shader texture_shader(
    string fileName = "",
    float offsetU = 0.0,
    float offsetV = 0.0,
    output color outColor = 0
){
    outColor = texture(fileName, u - offsetU, 1.0-v + offsetV);
}

Attribute Editor で offset U, offset V を変更すると、テクスチャ表示がスクロールされます。
このコードでは、offsetU, V を大きくすると右上に移動します。

MayaのaiOslShaderでoffsetUとoffsetVを変更し、テクスチャを右上へ移動した結果

テクスチャの繰り返し

テクスチャをリピートさせる方法についても解説します。

Maya ArnoldでOSLのwrapをperiodicに設定し、テクスチャを縦横に繰り返した結果

リピート数は入力により受け取ることができます。

shader texture_shader(
    float repeat_u = 2.0,
    float repeat_v = 2.0
){}

グローバル変数 u, v にそれぞれリピート数をかけて UV 座標を拡大します。

float s = u * repeat_u;
float t = (1.0-v) * repeat_v;

このままだと、座標 s, t は0.0~1.0の範囲に収まりません。
texture() の引数に”wrap”と“periodic”を設定することで、0.0~1.0の範囲外でも画像が繰り返されるようになります。

outColor = texture(fileName, s, t, "wrap","periodic");

wrapを使用せずに、値の小数部分だけを取り出し、座標を常に0~1の範囲へ戻してもOKです。

s = s - floor(s);
t = t - floor(t);

座標 s, t でテクスチャをサンプリングし、outColor に適用すれば、テクスチャがリピートします。

outColor = texture(fileName, s, t);

以上をまとめると、次のようなコードになります。

shader texture_shader(
    string fileName = "",
    float repeat_u = 2.0,
    float repeat_v = 2.0,
    output color outColor = 0
){
    float s = u * repeat_u;
    float t = (1.0-v) * repeat_v;
    outColor = texture(fileName, s, t, "wrap","periodic");
}

まとめ

今回は OSL におけるテクスチャについて解説しました。

  • texture(fileName, s, t) で画像の色を取得
  • Maya/Arnold 環境に合わせて V 座標を反転
  • 取得結果は color 型として演算できる
  • サンプリング座標を変えると移動・繰り返しを実装できる

今回学んだ方法を発展させれば、テクスチャを回転したり、ゆがませたり、自由な合成モードで組み合わせたり、色味を変更したりと、自由自在にテクスチャを扱えるようになります。

次回に続きます。

次回の記事: 未公開

コメント

タイトルとURLをコピーしました