
顔のクリッピング
立方体を想像して、あらゆる方向から見ることができる面の最大数を計算してみてください。 あなたの想像力があまり鮮明でない場合、おそらくこれが3番であるという結論に達するでしょう。どの点からも、キューブを見る方向からも、3つ以上の面を見ることができません。 それでは、残りの3つの顔が表示されていない場合、レンダリングに計算能力を浪費するのはなぜですか? 何らかの方法で処理を破棄できる場合は、フラグメントシェーダーの実行の半分以上を節約できました!
内容
パート1.はじめに
パート2.基本的な照明
パート3. 3Dモデルをダウンロードする
パート4.高度なOpenGL機能
パート5.高度な照明
パート6. PBR
パート2.基本的な照明
パート3. 3Dモデルをダウンロードする
パート4.高度なOpenGL機能
パート5.高度な照明
パート6. PBR
特定の状況では立方体の2つまたは1つの面しか表示されないため、「半分以上」と表示されます。 このような場合、50% 以上が保存されます。
アイデアは優れていますが、新しいタスクが表示されます。観察者の位置からどの顔が見えないかを判断する必要があります。
閉じた体積図を想像してください。各面には2つの側面があります。 そして、これらの側面の1つはオブザーバーに向かい、もう1つの側面はオブザーバーに向かいます。 観測者に面した顔だけを描くとどうなりますか?
このプロセスの中で、顔をカットする手順の本質があります。 OpenGLはすべての面の向きをチェックし、観察者に面している人だけをレンダリングに許可し、反対側の面を切り取ります。これにより、最終的にフラグメントシェーダへの呼び出しが大幅に節約されます(完了に非常にコストがかかります)。 どういうわけか、どの顔が顔と見なされ、どの顔がそうでないかに関する情報をOpenGLに伝える必要があります。 OpenGLは、面の向きを決定するために独創的なソリューションを使用します。頂点データリストでの走査順序の分析です。
回避策
三角形の頂点のセットを定義するとき、特定のトラバーサル順序で時計回り(時計回り、CW)または反時計回り(反時計回り、CCW)に定義します。 各三角形は3つの頂点で構成されており、三角形の中心を基準に定義された走査順序で定義します。

図からわかるように、最初の頂点1が設定され、次に、頂点2または3を設定する選択肢があります。これにより、三角形のトラバースの順序が決定されます。 わかりやすくするためのコードを次に示します。
float vertices[] = { // vertices[0], // 1 vertices[1], // 2 vertices[2], // 3 // vertices[0], // 1 vertices[2], // 3 vertices[1] // 2 };
最後に、三角形を定義する3つの頂点の各セットには、その走査順序に関するデータが含まれます。 準備したプリミティブをレンダリングするとき、OpenGLはこの情報を使用して、次の三角形が顔であるかどうかを判断します。 デフォルトでは、反時計回りに移動した三角形は顔と見なされます。
頂点セットでトラバーサルを定義するときは、三角形を直接見ているように提示し、三角形を反時計回りに設定する必要があります。 この架空のプロセスで最も興味深いのは、バイパス順序の直接処理がラスタライズの段階で発生することです。 頂点シェーダーを実行した後。 これは、頂点が実際に観察者の視点に変換されることを意味します。
観測者が見ている三角形のすべての頂点は、私たちが尋ねたのと同じ順序で実際に渡されていることがわかります。 しかし、同時に、立方体の反対側の三角形の頂点は、バイパスの順序が逆になるように表示されます。 その結果、観察者の前の三角形は顔と見なされ、遠くの三角形は非顔と見なされます。 言われたことをより明確にするために画像を見てください:

頂点のリストでは、両方の三角形を反時計回りの順序で決定しました(近くの三角形は1-2-3として定義され、背面の三角形も1-2-3として定義されています(観察者が正面を見た場合))。 ただし、指定された位置から、遠い三角形1-2-3の記述順序は時計回りに与えられます。 遠い三角形の頂点は反時計回りのトラバース順序で設定されていたにもかかわらず、レンダリングされると時計回りの順序になりました。 そして、そのような振る舞いは、目に見えない顔をうまくカットするために必要です。
エッジ除去
レッスンの始めに、OpenGLが三角形を非顔として表示されている場合、三角形を切り取ることができることに注意しました。 これで、バイパスの順序を設定する方法がわかったので、ライブラリでデフォルトで無効になっているクリッピング機能の使用を開始できます。
過去のレッスンのキューブの頂点データは、反時計回りの走査順序の要件を考慮して生成されていないため、ここにある新しい頂点の配列が必要です 。 練習-各三角形の横断の順序を精神的にチェックしてみてください。
次のようにして、クリッピング機能を有効にできます。
glEnable(GL_CULL_FACE);
これ以降、すべての非ファセット面は破棄されます(キューブの内部を見て、内面の表面が破棄されることを確認してください)。 その結果、フラグメントを処理するためのパスの50%以上を節約できますが、これはキューブのような閉じた図形に対してのみです。 前のレッスンでは、草を描いたオブジェクトは顔と顔以外の顔の両方を描画するため、顔のクリッピングをオフにする必要がありました。
OpenGLでは、面のどちら側を破棄するかを構成できます。 突然、フェースラインを破棄する必要がありますか? これを行うには、次の呼び出しを使用できます。
glCullFace(GL_FRONT);
この関数には、次の3つのパラメーターがあります。
• GL_BACK : 切り子のない面のみをドロップします。
• GL_FRONT :顔面のみを破棄します。
• GL_FRONT_AND_BACK :両方の面をドロップします。
デフォルト値はGL_BACKです。
破棄する面を選択することに加えて、三角形のどのバイパス順序が面を決定するかを指定できると便利です。 これを行うには、次の関数を使用します。
glFrontFace(GL_CCW);
デフォルト値はGL_CCWで 、反時計回りのトラバースを意味します。 2番目の可能な値はGL_CWで、時計回りのバイパスを設定します。
簡単な実験として、標準の反時計回りのトラバースではなく、正面を指定することで、非顔面のクリッピングと時計回りのトラバースを設定できます。
glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glFrontFace(GL_CW);
その結果、立方体の背面のみが表示されたままになります。

逆に、この効果は顔の顔をカットすることで実現できますが、顔の顔を定義するときに反時計回りのバイパスを使用する場合:
glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glFrontFace(GL_CW);
要約すると、面を切断するメカニズムは、生産性を向上させるための優れたツールであり、作業にほとんど労力を必要としないと言えます。 さらに、シーン内のどのオブジェクトがクリッピングを使用するのに有益であり、どのオブジェクトがクリップを受け入れられないかを追跡する必要があるだけです。
演習
頂点リストのデータを再定義して、各三角形が時計回りに定義されるようにしますか? 時計回りに説明されているように、顔の三角形を定義するときにシーンを表示します。
解決策はこちらです。
PPS :転送を調整するための電報confがあります。 サイクルに合わせたい場合は、大歓迎です!