-シンプル描画用 OSL スクリプト-

2. 光源の向きを同期する。影の判定をする。


先ほどの表示では、光源の向きはデフォルトでは上から照らされていて、変えようとすると手動で入力が必要でした。
シーンに設定した太陽光線の向きに自動でそろえられたほうが便利です。ここではドライバ機能を使って、光源の向きを同期させて見ます。

■ドライバで同期

CombineXYZを使えばベクトルを作成できるので、ここのXYZにドライバを設定することを考えます。
平行光線の光源「Sun」があるとします。
Sun の matrix_world[2][0], matrix_world[2][1], matrix_world[2][2] にSunの向き情報があるので、
ノードのX,Y,Zの値が同期するようにドライバで設定をします。
このように、光源「Sun」の向きに同期するようなベクトルが LightVecのソケットにつながるようにします。
このように、光源の向きにしたがって陰影がつきました。
通常の Diffuse のマテリアルのオブジェクトを並べて、光源の方向が間違えていないことを確認します。

■ 影の判定

この時点で重大な欠点として、影の表現ができていません。いくらシンプルな表現とはいえ、ちょっとシンプルすぎます

OSLの中に、trace というコマンドがあり、OSLの計算中に、ある地点から光線を飛ばして何かオブジェクトにぶつかるかどうか、という判定をすることができます。
これを利用することで、光源の方向に光線を飛ばして、何らかのオブジェクトにぶつかれば影、そうでなければ光に照らされている、という区別をすることができます。

traceコマンドの戻り値は、何かにぶつかれば1、そうでなければ0なのでそれを利用して影か影でないかを判定しています。

shader simple(
    color ambient = color(0.3, 0.3, 0.3),
    color diffuse = color(0.7, 0.7, 0.7),
    color specular = color(0.5, 0.5, 0.5),
    float specularPower = 24,
    vector lightVec = vector(0, 0, 1),
    output color Color = ambient
)
{
    float diffFactor = max(0, dot(N, lightVec));
    float specFactor = 0;
    if (diffFactor > 0) 
        specFactor = pow(max(0, dot(I, 2 * N * dot(N, lightVec) - lightVec)), specularPower);
        
    float shadow = 1;
    if (diffFactor != 0)
        shadow = trace(P, lightVec);
        
    Color = ambient + (1-shadow)*(diffFactor * diffuse + specFactor * specular);
}

trace 計算は比較的重い処理ということなので、ここで、若干の高速化の工夫がしてあります。
diffFactor (散乱光の評価値)が 0 であれば、すなわち光源の反対向きを向いた面であるので、trace 計算するまでもなく必ず影になっていることにしています。
(注:スムーズ化によって、ポリゴンの本当の向きと法線の向きに差が出てくるので、この方法は形状によっては影に乱れがでることがあります)


これで、オブジェクトから落ちる影が表現できました。
半透明な物体などの区別をすることはできませんが、最小限の表現力はあるといって良いでしょう。
シンプルな質感のマテリアルを サンプル数の非常に低い Cycles で高速にレンダリングすることができました。

Emission の他にサンプル数が0でもノイズがのらないシェーダーは、Roughness(荒さ)を0に設定した Gloss (反射) と Refraction (屈折) 、その他、Transparent(透明)、そして背景になります。また、これらを Mix や Add でシェーダーを混ぜるとノイズが乗りはじめますが、Emission との組み合わせの場合のみは 組み合わせてもノイズが乗らずにすむようです。

本当のガラス表現は、Gloss と Refraction を組み合わせたものになるのですが、残念ながらこの2つを組み合わせるとサンプル数1だとノイズが乗るようになるので、ガラスというよりプラスチックのような表現までしかできません。
(もちろんサンプル数を上げることを許容すればガラスの表現も可能ですが、遅くなります)

※ この記事は Blender Advent Calendar 2018 に合わせて公開したものです。

次の記事はhonjo_KEELさんのhttps://zergauza.com/2018/12/15/です。

inserted by FC2 system