複数のシェーダーを使用する


53

私は現在openglシェーダーを研究していますが、何かを理解することはできません:オブジェクトに異なるシェーダーを適用する方法、たとえば、トゥーンシェーダーを使用してレンダリングされたティーポットと、非常に反射性の表面および他のこのビデオのようなノイズ関数

http://www.youtube.com/watch?v=1ogg4ZfdBqU

もう1つは、シーンにブルームシェーダーを適用し、その後でモーションブラーシェーダーを適用することです。1つの頂点シェーダーと1つのフラグメントシェーダーのみを使用できる場合に、これらの効果を実現するにはどうすればよいですか?複数のシェーダープログラムを使用するなどのトリックはありますか?


ネイサンとデビッドの良い答えについて、これがレンダーパスまたはシェーダーパスという用語を見る理由です。最終的な画像/フレームを構成するには複数のパスが必要です。GPU処理が非常に並列化され、高速になった理由の1つは、フレームごとに複数のパスが必要なことです。Quake IIまたはHalf Lifeソフトウェアレンダラーに戻り、3Dグラフィックスエクスペリエンス全体にどれだけの愛のシェーダーパスが追加されるかを思い出してください。
エンジニア

回答:


59

簡単な答えは、各ドローコール間でそれらを変更することです。シェーダーを設定し、ティーポットを描画し、別のシェーダーを設定し、別のティーポットを描画します。

ぼかし、グローなど、1つのオブジェクトだけに複数のシェーダーを適用する必要がある、より複雑なもの。基本的に、すべてがテクスチャにレンダリングされます。次に、別のシェーダーを使用しながら、テクスチャを適用して画面全体にクワッドをレンダリングします。

たとえば、グローエフェクトをレンダリングする場合、通常の非グローシーンをレンダリングする必要があります。次に、テクスチャでグローしたいものの色付きのシルエットだけをレンダリングしてから、ぼかしシェーダーに切り替えてレンダリングします。輝きのないシーンにそのテクスチャがアタッチされたクワッド。

遅延シェーディングと呼ばれる別の手法があります。この手法では、照明なしでシーンをレンダリングし、後で画面スペースに適用します。コア目標は、ピクセルごとの照明の費用を削減することです。

通常、画面に配置されるカラーバッファーをレンダリングします。遅延シェーディングでは、代わりに1つのシェーダーパスでカラーバッファーと法線と深度バッファーをレンダリングします(法線と高さのマッピングのように、法線ベクトルと深度をテクスチャに格納できます)。

これは、すべてのピクセルについて、最も近い透明でないジオメトリの部分(深さまたは目からの距離)の色と法線を知っていることを意味します。このため、レンダリングするすべてのオブジェクトの各表示ピクセルにではなく、画面上の各ピクセルに照明を適用できます。シーンが前後の順序で完全にレンダリングされない場合、一部のオブジェクトは他のオブジェクトの上に描画されることに注意してください。

影の場合、実際にはライトの視点から深度バッファーのみをレンダリングし、その深度情報を使用してライトが当たる場所を判断します。これは、シャドウマッピングと呼ばれます(ジオメトリのシルエットを作成して押し出すシャドウボリュームと呼ばれる別のアプローチもありますが、それでもシェーダーを使用します)。

より近代的なOpenGLの(3.0+)を使用すると、使用フレームバッファオブジェクトレンダとが接続されるオブジェクト。レンダバッファはテクスチャのように扱うことができるため。あなたは(あなたが、あなたの法線を、あなたのテクスチャをレンダリングする必要はありませんので、複数の異なるレンダに1つのシェーダをレンダリングしているようなこと行う可能性があり、その後グローコンポーネント)が、根本的な練習はまだ同じです。

また、オーバーヘッドを節約するために、シェーダースイッチの数をできるだけ少なくすることが望ましいです。そのため、一部のエンジンは、すべてを一度に描画できるように、同じマテリアルを使用してすべてをグループ化します。


16

1つのシェーダーをバインドし、そのシェーダーを使用してすべてのオブジェクトをレンダリングしてから、次のシェーダーをバインドし、そのシェーダーを使用してオブジェクトをレンダリングするだけです。

必要な数のシェーダーオブジェクト(メモリにロードされコンパイルされたシェーダー)を持つことができます。一度に1つしかバインド(アクティブ)できません。


5
実装に関しては、すべてのフレームでglUseProgram(1)とglUseProgram(2)を使用してシェーダーを変更しますか?それはパフォーマンスにどのくらいの費用がかかりますか?
ibrabeicker

4
それは重要なコストです(ただし、最近のGPUでは以前のGPUよりも少ない)。そのため、ほとんどの人はオブジェクトをマテリアルでソートし、すべてのオブジェクトを同じマテリアルでレンダリングします。ただし、フレームごとにプログラムを数十回から数百回変更することもできます。
ネイサンリード

9

シーンで複数のシェーダーを使用するのは非常に簡単です。シェーダーを変更して値を設定し、オブジェクトをレンダリングします。

ただし、シェーダーの切り替えにはコストがかかるため、シェーダーの切り替えは最小限に抑える必要があります。必要な効果をすべて得ながら、この影響を減らす方法がいくつかあります。

最初の方法で、通常最も望ましいのは、すべてのシェーダーテクニックの機能を1つのシェーダーに追加し、設定した条件を使用して、同じシェーダーで各オブジェクトを異なる方法でレンダリングすることです。OpenGLシェーダーとGLSLシェーダーについては知りませんが、HLSLシェーダーとDirectXでは、これらを「テクニック」としてグループ化でき、シェーダーを変更する代わりにテクニックを設定できます。これにより、同じファイルに複数の異なるピクセルシェーダーと頂点シェーダーを実際に配置できます。

パフォーマンスへの影響を減らす2番目の方法は、シェーダーを設定し、そのシェーダーを使用するすべてのオブジェクトをレンダリングしてから繰り返すことです。つまり、レンダリングをバッチ処理します。

同じオブジェクトに2つの異なる効果を適用する場合(つまり、トゥーンシェーダーを適用し、次に照明を適用する場合)、2つの異なる方法で実行できます。1つは、同じ関数に複数の効果を適用するシェーダーを記述することです。2番目の方法は、各シェーダーでモデルを1回レンダリングし、異なるブレンドオプションを設定して結果をブレンドすることです。ただし、これはより多くの作業であり、すべての状況で達成できるわけではありません。したがって、最良のオプションは、すべてのエフェクトを1つのシェーダーに結合することです。


7

私が発見した別の方法は、glslサブルーチンと呼ばれるものを使用することです。この場合、各タイプのシェーダーは1つの関数で定義され、OpenGLアプリケーションでは、現在のサブルーチンを定義し、バッファーの頂点を描画し、サブルーチンを変更し、別のバッファのレンダリング


4
これには、GL 4.x対応のハードウェアが必要です。これは、DX11クラスのハードウェアです。
ニコルボーラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.