フレームバッファ

はじめに

ここでは、レイヤ化シェーダがユーザのフレームバッファのパスに書き込む仕組みを説明します。この仕組みは、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

フレームバッファの名称とその意味は、次のとおりです。

direct_diffuse
拡散光を直接当てるライティングです。光はライト(L)から拡散反射(<RD>)サーフェスを経由して視点(E)に至るパスを移動します。
indirect_diffuse
間接光(拡散光)を当てたシーンです。光は任意の数のサーフェスにヒットできます。最終的な拡散サーフェスが視点に届く前に、反射または通過が発生します。
direct_glossy
光沢のある光を直接当てるライティングです。光はライトから光沢のある反射サーフェスを経由して視点に至るパスを移動します。
indirect_glossy
光沢反射が照明から直接来ていない。一般的に、従来のハイライトと反射のパスは、正確には直接反射や間接反射ではなく、むしろ直接光のループとレイ トレーシングした反射光線です。これは、見えている領域の光がハイライトではなく従来の反射パスになってしまう可能性を意味します。そこで、ライト パス エクスプレッションのモデルを使用して、直接光と間接光のパス指定にさらに厳密に従います。
direct_specular
スペキュラ直接ライティング(光源からスペキュラ サーフェスを経て目に入る)。鏡のようなサーフェスから直接光が反射しています
indirect_specular
スペキュラ反射は、光源から直接ではなく、対象物から来ています。
diffuse_transmission
半透明性エフェクトです。直接と間接の両方です。
glossy_transmission
ぼかしが入った屈折透過です。直接と間接の両方です。
specular_transmission
ぼかしのない屈折透過です。直接と間接の両方です。
front_scatter
「正面」を向いたサブサーフェスのエフェクト。
back_scatter
「背面」を向いたサブサーフェスのエフェクト。
emission
任意の"追加のライト"/自己照明/白熱光のエフェクト。
mila_adapter シェーダを使用します。

例:

いくつかのレイヤを含むサンプル シーンで、不透明なロボットの手前に単純な透明球体を配置します。この場合、透明は、中空ではないガラスの球体とは反対の概念であり、薄いガラスの球面を表現します。このほうがスペキュラ透過コンポーネントでの実装に適しています。

ビューティー レンダリング

Image:framebuffer-final-render.jpg
これは、さまざまなマテリアルを含むサンプル シーンです。正面の近くにある青い球体は、「透明」を使用して(スペキュラ透過ではなく)、自身の背後にあるシーンの一部を表示しています。

単純な従来の方式を使ったフレームバッファのパス

一般的には、一番上にあるオブジェクトに関するシェーダがフレームバッファに値を出力します。不透明なオブジェクトでは、これは拡散パスと反射パスのすべてで鮮明に表示されます。ただし、光を通すオブジェクトの場合、レンダラはバックグラウンドにあるオブジェクトに対してシェーダを実行します。したがって、制作上で重要となるのは、バックグラウンドのオブジェクトがどのフレームバッファのパスに関与するのか?という疑問です。

単純な実装では、最上位のシェーダが最上位オブジェクトの後ろにある物の完全な結果(つまりビューティ パス)を使って値を別個の"透明"パスに出力します。このように見える場合があります。

Image:framebuffer-current-behavior.jpg

ここでは、mia_material_x のさまざまな出力を示します。サーフェスを間接と直接の拡散、スペキュラ(直接スペキュラまたはハイライト)、および反射(間接スペキュラ)に分割しています。こうすることで、これらのサーフェスの外観を制作後の工程で微調整することができます。ただし、これらのそれぞれで、青の球体は完全に不透明に表示されます。

透明度を持つオブジェクト(この青い球体など)では、シェーダの透明度の出力の中にその後ろ側にオブジェクトが含まれます。この透明度の出力は、今後拡散やスペキュラなどの部分に分けられることはありませんが、バックグラウンド オブジェクトに対するビューティ パスのような合成された最終形態として、まとめて出力されます。

利点

欠点

全体的に、オブジェクト全般に対してのコントロールが不足しています。透明で表示されるものは「追従」しません。ウェイトの付け直しが合成段階で他の加算パスに適用される場合があるためです。透明は、完全に独立し、別のライトパスに対してコントロールがありません。

過去に、この問題に対処できるフレームバッファのシェーダが、複雑なシェーディング網を構築しようと考えるユーザのために開発されたことがあります。実際、弊社でもいくつかのバージョンを開発しテストしましたが、その使用法をサポートするのは困難だったでしょう。ただし、フレームバッファのサポートをこのライブラリのレイヤ化機能の中に組み込むことによって、使いやすさとパフォーマンスの両面で欠点の一部を単純化できると信じています。

レイヤ シェーダを使用したフレームバッファのパス

レイヤ化シェーダ ライブラリでは、どの要素コンポーネントが実行されているかを知ることに基づいて出力を作成できます。ライト パス エクスプレッションに関しては、要素シェーダによって、視点の前のコンポーネントのインタラクションの段階が識別され、そのインタラクションの入射光が直接か間接かどうかが決まります。たとえば、"L<RD>E" は mila_diffuse_reflection の内部に当たる直接光によって識別することができます。間接光は "L.+<RD>E" で表現されます。

透明度の出力を "L.*<TS>E" にすることもでき、スペキュラ透過からの影響もある可能性があります。視点から透明を通過して届くインタラクション(拡散、光沢、スペキュラ)を分離することも可能です。コンポジタがさまざまなサブ出力を、視点から直接見える(透明のオブジェクトを通過しない)個別出力の中に追加する準備ができていると見なす場合があります。

利点

欠点

フレームバッファ、モーション ブラーの実行方法

まだこのスタイルの透明度の動作が分からない場合、モーション ブラーの動作方法について考えます。

次の例では、青い球をわずかに透明にするのではなく、単にそれを高速に移動させ、モーション ブラーによって部分的に透明にしています。これは、古いシェーダの動作でも出力される結果です。

Image:framebuffer-motionblur-rendering.jpg

個々のフレーム バッファは次のようになり、レイヤ シェーダを使用しなくてもレンダーできます。

Image:framebuffer-motionblur-behavior.jpg

次に示すように、正確な結果はレンダラにより自動的に行われました。サンプルをピクセル集約したとき、結果は正確に期待したものになります。

この場合、「透明度」出力がないことも意味をなします。オブジェクトには透明度すらありません。速度によってこのように見えるだけです。

したがって、レイヤ化シェーダの透明機能を使うことで、同じことが実現できます。合成が簡単になり、コントロールの範囲が広がり、最終結果に合成アーティファクトが発生しにくくなります。

ラスタライザが使用されている場合は、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 乗が適用され、個々の「結果」出力の乗算に一致しないからです。

最後に、ピクセルがフィルタされているため、さまざまなサンプルからの多くの最終結果がウェイト付けされ、混合されることに注意してください。これによって、数学上の複雑さが増します。オブジェクトのエッジでは単純なパスにまでも影響を及ぼします。オブジェクト上のエッジが、パスなど使用した結果、暗くなったり、他のアーティファクトが見えたりすることがよくあります。さまざまな基本光量のみ追加するパスを使用して最終画像を作成する場合は、この問題を完全に回避します。合成中に要素の組み合わせの問題が起こらないように、追加のみのパスを使用してください。