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

1. Cyclesで超シンプルな描画をする

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



Cycles はリアルな絵を作るにはいいけど、リアルじゃない絵でよいとか、リアルじゃない絵がよい、というような場合には、必要以上に処理が重くて素早い表示ができません。
サンプル数を減らせば速くなりますが、ノイズがのってしまいます。

すばやい描画が必要なときには、blender 2.80 から導入される Eevee レンダラが対応するわけですが、反射、屈折など、(本来は)レイトレーシングが必要な効果などは不正確な時がある、魚眼カメラなどがまだ無い、などの短所があります。

ここの内容は、OSL (Open Shading Language) を使って、サンプル数1でもノイズが乗らない、超簡単な描画用のマテリアルを作り、Cycles をサンプル数 1 でレンダリングして、高速に運用してみようという内容です。もちろん、得られる絵はとてもシンプルです。

Blender のスクリプトといえば、普通は Python ですが、OLS は、C言語に似た言語です。
C言語の系列の言語の経験がないと戸惑うところがあるかもしれませんが、ここではそんなに難しいスクリプトは使いません。
OSLの仕様は、ここからpdfファイルを入手できます。
ただし、blender が OSL の仕様すべてを実装しているわけではないので、一部の機能が使えなかったりします。(基本的な機能はほぼ実装しているものと思いますが…)

■基本環境設定

大前提として Cycles レンダーに設定します。
OSLを有効にします。OSLは CPU で描画するときのみ使うことができます。



サンプル数を1にします。Cyclesでもっとも速くレンダリングできる設定です。
マテリアルノードで、とりあえず Diffuse にしてみますが…
当然非常にノイジーです。
Diffuse に限らず、たいていのシェーダーはサンプル数1では実用に耐えないほどノイズがのるはずです。
しかし、Emission の場合は、光のあたり具合の評価などは関係ないので
ノイズは乗りません。ただしもちろんこれでは単色です。
ここで、色を光源からの向きにしたがって変化できるような OSL スクリプトを作成してみます。


■OSLスクリプト作成

Script シェーダーを配置します。外部ファイル、もしくは内部のテキストデータを選択して、実行することができます。
左のようなスクリプトを組みんでみます。
入力情報と、出力情報を記述しました。
色設定と光源の方向を入力情報として、結果を出力するための output が1つあります。
スクリプトシェーダーで入力したスクリプトを指定して更新すれば、入力と出力のソケットが作成されていることが分かります。
出力ソケットを Emission シェーダーに接続すれば、色を OSL で制御できることになります。

光源の向きにしたがって、明るさを評価する式として以下のような式を組みました。
散乱光、光沢を表現するために一般的に使われるような式です。
(Lambert 散乱と、Phong の スペキュラーのモデル)

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);
    Color = ambient + diffFactor * diffuse + specFactor * specular;
}

入力ソケットで宣言していない変数が幾つか使われていますが、これは OSL上でデフォルトで最初に定義されるグローバル変数で、
N: 法線の方向
I: ビューベクトル(視線の方向)
となります。その他 P (位置) なども用意されています。
(これらのグローバル変数は、グローバル座標での値になっています。)



例にあるスクリプトでレンダリングした画像はこのようになります。Emission のみを使ってサンプル数1なので(Eeveeほどではないにせよ)高速で、プレビュー画面でぐるぐる視点を動かすことにも充分耐えられます。



ただし、サンプル数1だと本当に1ピクセルあたり1回計算するだけなので、アンチエイリアスはかかりません。
最終レンダリングをするときには、少なくとも4、綺麗な絵の場合はサンプル数16程度の数が必要のようです。

inserted by FC2 system