Arnold 5.0 では、サーフェスおよびボリューム シェーダは最終的なカラーではなくクロージャを返します。クロージャは、ライトのループや Arnold への統合を維持したまま、サーフェスおよびボリュームが光を散乱する方法を記述します。このようなアプローチにより、さらなる最適化と、より優れたレンダリング アルゴリズムが実現します。
BSDF および BSSRDF クロージャは、サーフェスの上および下に光を散乱する方法を定義します。
拡散反射光 BSDF
// OSL
result = 0.8 * diffuse(N);
// C++
sg->out.CLOSURE() = AiOrenNayarBSDF(sg, AtRGB(0.8f), sg->Nf);
BSSRDF
// OSL
result = weight * empirical_bssrdf(mean_free_path, albedo);
// C++
sg->out.CLOSURE() = AiClosureEmpiricalBSSRDF(sg, weight, mean_free_path, albedo);
屈折では、BSDF はオブジェクトの内部を定義する内部クロージャ リスト パラメータを取ります。これは、ガラス内部でのボリュームの吸収や散乱のモデリングなどに使用できます。
BSSRDF
// C++
AtClosureList interior = AiClosureVolumeAbsorption(sg, absorption_coefficient);
sg->out.CLOSURE() = AiMicrofacetRefractionBSDF(sg, ..., interior);
発光クロージャは、サーフェスから光を発光するのに使用します。
発光
// OSL
result = intensity * color * emission();
// C++
sg->out.CLOSURE() = AiClosureEmission(sg, intensity * color);
サーフェスは既定では不透明です。透明およびマット クロージャは、サーフェスを透明にしたり、アルファ チャネルに影響を与えるのに使用します。サーフェスを透明またはマットにした場合は、他のサーフェス クロージャのウェイトもそれに従って削減されます。これは、全クロージャの合計ウェイトが 1 を超えないようにしてエネルギーを節約するためです。他のクロージャとの混合は、次のように実行できます。
透明度を持つ拡散反射光 BSDF
// OSL
result = opacity * 0.8 * diffuse(N) + (1 - opacity) * transparent();
// C++
AtClosureList closures;
closures.add(AiOrenNayarBSDF(sg, opacity * AtRGB(0.8f), sg->Nf));
closures.add(AiClosureTransparent(sg, 1 - opacity));
sg->out.CLOSURE() = closures;
透明クロージャは、サーフェスを透明にしてその背後にあるオブジェクトを表示します。マット クロージャは、アルファ チャネルに穴を作成すると同時に、サーフェスの背後のオブジェクトをブロックします。レンダリング後のイメージに他のオブジェクトをコンポジットするために使用できます。
不透明度とアルファの関係は次のようになります。
opacity = 1 - transparent
alpha = 1 - transparent - matte
最適なパフォーマンスを得るには、確率的透明度を使用します。OSL シェーダの場合、確率的透明度は自動的に適用されます。C++ の場合は次のようにして適用します。シャドウ レイの場合、必要なのは不透明度だけで、BSDF の作成とシャドウ レイに必要なパラメータの評価は、最適なパフォーマンスを得るためにスキップする必要があります。
確率的透明度
// handle opacity
AtRGB opacity = AiShaderGlobalsStochasticOpacity(sg, AiShaderEvalParamOpacity(p_opacity));
if (opacity != AI_RGB_WHITE)
{
sg->out.CLOSURE() = AiClosureTransparent(sg, AI_RGB_WHITE - opacity);
// early out for nearly fully transparent objects
if (AiAll(opacity < AI_OPACITY_EPSILON))
return;
}
// early out for shadow rays
if (sg->Rt & AI_RAY_SHADOW)
return;
// create shader closures
AtClosureList closures = ...;
// write closures
if (opacity != AI_RGB_WHITE)
{
closures *= opacity;
sg->out.CLOSURE().add(closures);
}
else
{
sg->out.CLOSURE() = closures;
}
ボリューム クロージャのウェイトは吸収、散乱、ボリュームの各係数に基づきます。値を高くするほど、ボリュームの密度は高くなります。シャドウ レイには吸収のみが必要なため、散乱と発光の計算をスキップすることで、これらに必要な関連パラメータの評価を回避できます。
ボリューム
// OSL
if (raytype("shadow"))
result = density * volume_absorption();
else
result = density * volume_henyey_greenstein(absorption, scattering, emission, anisotropy);
// C++
if (sg->Rt & AI_RAY_SHADOW)
sg->out.CLOSURE() = AiClosureVolumeAbsorption(sg, AtRGB(density));
else
sg->out.CLOSURE() = AiClosureVolumeHenyeyGreenstein(sg, density * (1 - scattering),
density * scattering,
density * emission,
anisotropy);
クロージャを使用するシェーダはライティングを AOV に書き込むことができません。代わりに、ライト パス エクスプレッション AOV を使用できます。