ここでは、レイヤ化シェーダがユーザのフレームバッファのパスに書き込む仕組みを説明します。この仕組みは、mia_material_x シェーダで過去に使用したものとは異なっています。この部分では、よりシンプルなパイプライン手法を促進する方法について、特定の統合形態に役立つ情報を提供できるかもしれません。したがって、このページでは、古い方法の欠点を明らかにし、この新しい方法が制作用途により適している理由を説明します。
最小限の準備で済むように、カメラ用に特別に名前を付けたフレームバッファを指定します。標準の名前を使用してシンプルにフレームバッファを作成します。次に、シーン記述言語でフレームバッファを指定した例を示します。
framebuffer "indirect_diffuse"
datatype "rgba_16"
filtering true
filename "passes.exr"
compression "rle"
premultiplied true
user true
useopacity true
attribute string "LPE" "L.+<RD>E"
framebuffer "direct_diffuse"
datatype "rgba_16"
filtering true
filename "passes.exr"
compression "rle"
premultiplied true
user true
useopacity true
attribute string "LPE" "L<RD>E"
...
... etc repeated for all the buffers
...s
フレームバッファの名称とその意味は、次のとおりです。
いくつかのレイヤを含むサンプル シーンで、不透明なロボットの手前に単純な透明球体を配置します。この場合、透明は、中空ではないガラスの球体とは反対の概念であり、薄いガラスの球面を表現します。このほうがスペキュラ透過コンポーネントでの実装に適しています。
一般的には、一番上にあるオブジェクトに関するシェーダがフレームバッファに値を出力します。不透明なオブジェクトでは、これは拡散パスと反射パスのすべてで鮮明に表示されます。ただし、光を通すオブジェクトの場合、レンダラはバックグラウンドにあるオブジェクトに対してシェーダを実行します。したがって、制作上で重要となるのは、バックグラウンドのオブジェクトがどのフレームバッファのパスに関与するのか?という疑問です。
単純な実装では、最上位のシェーダが最上位オブジェクトの後ろにある物の完全な結果(つまりビューティ パス)を使って値を別個の"透明"パスに出力します。このように見える場合があります。
ここでは、mia_material_x のさまざまな出力を示します。サーフェスを間接と直接の拡散、スペキュラ(直接スペキュラまたはハイライト)、および反射(間接スペキュラ)に分割しています。こうすることで、これらのサーフェスの外観を制作後の工程で微調整することができます。ただし、これらのそれぞれで、青の球体は完全に不透明に表示されます。
透明度を持つオブジェクト(この青い球体など)では、シェーダの透明度の出力の中にその後ろ側にオブジェクトが含まれます。この透明度の出力は、今後拡散やスペキュラなどの部分に分けられることはありませんが、バックグラウンド オブジェクトに対するビューティ パスのような合成された最終形態として、まとめて出力されます。
利点
欠点
全体的に、オブジェクト全般に対してのコントロールが不足しています。透明で表示されるものは「追従」しません。ウェイトの付け直しが合成段階で他の加算パスに適用される場合があるためです。透明は、完全に独立し、別のライトパスに対してコントロールがありません。
過去に、この問題に対処できるフレームバッファのシェーダが、複雑なシェーディング網を構築しようと考えるユーザのために開発されたことがあります。実際、弊社でもいくつかのバージョンを開発しテストしましたが、その使用法をサポートするのは困難だったでしょう。ただし、フレームバッファのサポートをこのライブラリのレイヤ化機能の中に組み込むことによって、使いやすさとパフォーマンスの両面で欠点の一部を単純化できると信じています。
レイヤ化シェーダ ライブラリでは、どの要素コンポーネントが実行されているかを知ることに基づいて出力を作成できます。ライト パス エクスプレッションに関しては、要素シェーダによって、視点の前のコンポーネントのインタラクションの段階が識別され、そのインタラクションの入射光が直接か間接かどうかが決まります。たとえば、"L<RD>E" は mila_diffuse_reflection の内部に当たる直接光によって識別することができます。間接光は "L.+<RD>E" で表現されます。
透明度の出力を "L.*<TS>E" にすることもでき、スペキュラ透過からの影響もある可能性があります。視点から透明を通過して届くインタラクション(拡散、光沢、スペキュラ)を分離することも可能です。コンポジタがさまざまなサブ出力を、視点から直接見える(透明のオブジェクトを通過しない)個別出力の中に追加する準備ができていると見なす場合があります。
利点
欠点
まだこのスタイルの透明度の動作が分からない場合、モーション ブラーの動作方法について考えます。
次の例では、青い球をわずかに透明にするのではなく、単にそれを高速に移動させ、モーション ブラーによって部分的に透明にしています。これは、古いシェーダの動作でも出力される結果です。
個々のフレーム バッファは次のようになり、レイヤ シェーダを使用しなくてもレンダーできます。
次に示すように、正確な結果はレンダラにより自動的に行われました。サンプルをピクセル集約したとき、結果は正確に期待したものになります。
この場合、「透明度」出力がないことも意味をなします。オブジェクトには透明度すらありません。速度によってこのように見えるだけです。
したがって、レイヤ化シェーダの透明機能を使うことで、同じことが実現できます。合成が簡単になり、コントロールの範囲が広がり、最終結果に合成アーティファクトが発生しにくくなります。
ラスタライザが使用されている場合は、useopacity フラグが true でなくてはならないことに注意することが重要です。その理由は、最終サンプルをフレーム バッファのピクセルに合成するのはラスタライザの管轄だからです。
注意すべき点は、この動作は、数学的に追加されるライトのサブコンポーネントであるすべての出力について完全に意味をなすということです。次のようなその他のさまざまな種類の出力では意味をなしません。
レイヤ シェーダは、マテリアル ルート ノード mila_material 上で特殊な「余剰出力」を使用することで、前者をサポートすることができます。
しかし、2 つ目の問題を解決するのは数学的には不可能です。次のセクションで説明します。
mia_material シェーダには、すべての種類の出力、すなわち「未処理」、「レベル」、および「結果」があります。一般的に言うと、
では、これらのシェーダが、これらすべての出力を行い、それらすべてを適切にミックスできないのはなぜでしょうか。
その答えは、パスがピクセルに変わったら、そこから混合を作成しなおすことが数学的に不可能だからです。
2 つの拡散マテリアル A と B があり、A を 80%、B を 20% の割合で混合することにします。さらに、これらのシェーダに「結果」、「未処理」、「レベル」の出力があるとします。
A.result = A.raw * A.level B.result = B.raw * B.level
混合した最終的な結果は、次のようになります。
final.result = A.result * 80% + B.result * 20%
...ただし、他の出力を混合することはできません。例:
final.raw = A.raw * 80% + B.raw * 20% final.level = A.level * 80% + B.level * 20%
...その次に、
final.raw * final.level = ((A.raw * 80%) + (B.raw * 20%)) *((A.level * 80%) + (B.level * 20%)) final.raw * final.level = (A.result * 80%) * 80% + (B.result * 20%) * 20% + more multiplying terms ... final.result != final.raw * final.level
...その理由は、ウェイトが「未処理」および「レベル」の両方に適用されて、それらを合わせて乗算すると、実質的にはウェイトの 2 乗が適用され、個々の「結果」出力の乗算に一致しないからです。
最後に、ピクセルがフィルタされているため、さまざまなサンプルからの多くの最終結果がウェイト付けされ、混合されることに注意してください。これによって、数学上の複雑さが増します。オブジェクトのエッジでは単純なパスにまでも影響を及ぼします。オブジェクト上のエッジが、パスなど使用した結果、暗くなったり、他のアーティファクトが見えたりすることがよくあります。さまざまな基本光量のみ追加するパスを使用して最終画像を作成する場合は、この問題を完全に回避します。合成中に要素の組み合わせの問題が起こらないように、追加のみのパスを使用してください。