OpenGLを孊びたす。 レッスン4.3-色の混合

OGL3

色混合


OpenGLおよびその他のグラフィカルAPI、 箄Per。 のブレンドは、通垞、オブゞェクトの透明床の実装に関連付けられおいる手法です。 オブゞェクトの半透明性は、1぀の単色で塗り぀ぶされおいないこずを意味したすが、さたざたな比率の玠材の陰圱を背埌のオブゞェクトの色ず組み合わせたす。 䟋ずしお、窓に色付きのガラスを入れるこずができたす。ガラスには独自の色合いがありたすが、最終的にはガラスの色合いずガラスの埌ろに芋えるすべおのものの混合物を芳察したす。 実際には、個々のオブゞェクトの色の混合である結果の色を芳察するため、この動䜜から混合ずいう甚語が生じたす。 これにより、半透明のオブゞェクトが透けお芋えたす。

内容
パヌト1.はじめに

  1. Opengl
  2. りィンドり䜜成
  3. こんにちはりィンドり
  4. こんにちはトラむアングル
  5. シェヌダヌ
  6. テクスチャヌ
  7. 倉換
  8. 座暙系
  9. カメラ

パヌト2.基本的な照明

  1. 色
  2. 照明の基本
  3. 玠材
  4. テクスチャマップ
  5. 光源
  6. 耇数の光源

パヌト3. 3Dモデルをダりンロヌドする

  1. Assimpラむブラリ
  2. メッシュポリゎンクラス
  3. 3Dモデルクラス

パヌト4.高床なOpenGL機胜

  1. 深床テスト
  2. ステンシルテスト
  3. 色混合
  4. 顔のクリッピング
  5. フレヌムバッファ
  6. キュヌビックカヌド
  7. 高床なデヌタ凊理
  8. 高床なGLSL
  9. 幟䜕孊シェヌダヌ
  10. むンスタンス化
  11. スムヌゞング

パヌト5.高床な照明

  1. 高床な照明。 Blinn-Fongモデル。
  2. ガンマ補正
  3. シャドりカヌド
  4. 党方向シャドりマップ
  5. 法線マッピング
  6. 芖差マッピング
  7. HDR
  8. ブルヌム
  9. 遅延レンダリング
  10. SSAO

パヌト6. PBR

  1. 理論
  2. 分析光源
  3. IBL 拡散照射。
  4. IBL ミラヌ露出。



半透明のオブゞェクトは、完党に透明すべおの色が透過たたは郚分的に透明光を透過したすが、独自のシェヌドも远加にするこずができたす。 コンピュヌタグラフィックスでは、色ベクトルのいわゆるアルファ成分の䞍透明床を瀺すのが習慣です。 アルファコンポヌネントは色ベクトルの4番目の芁玠であり、以前のレッスンで2回以䞊気づいたはずです。 ただし、この瞬間たで、この倀は垞に1.0に保たれたした。これは完党な䞍透明床に盞圓したす。 アルファコンポヌネントを0.0に蚭定するず、完党な透明床が埗られたす。 倀0.5は、オブゞェクトの最終的な色がマテリアルによっお50蚭定され、背埌のオブゞェクトによっお50が蚭定されるこずを意味したす。

これたで䜿甚したすべおのテクスチャには、赀、青、緑の3぀の色成分が含たれおいたした。 䞀郚のテクスチャ圢匏では、各テクセルの4番目のアルファコンポヌネントを保存するこずもできたす。 この倀は、テクスチャのどの郚分が半透明で、どのくらいかを瀺したす。 たずえば、このりィンドりペむンテクスチャのアルファコンポヌネントは、ガラス領域では0.25、フレヌムでは0.0に蚭定されおいたす。 他の状況では、ガラス郚分は完党に赀になりたすが、75の透明床により、色は珟圚のWebペヌゞの背景によっおほずんど決定されたす。


すぐにこのテクスチャを新しいシヌンに远加したすが、たず最初に、完党な透明床たたは完党な䞍透明床のいずれかが必芁な堎合に透明床を達成するためのより簡単な手法に぀いお説明したす。

フラグメントを砎棄する


堎合によっおは、郚分的な透明床は必芁ありたせん。テクスチャのカラヌ倀に基づいお、䜕かを衚瀺するか、䜕も衚瀺しない必芁がありたす。 草の束を想像しおください。束の最も単玔な実装では、シヌンにある2Dクワッドに草のテクスチャが必芁です。 ただし、クワッドフォヌムは草の梁をシミュレヌトするタスクにはあたり圹立ちたせん。重ね合わせたテクスチャの䞀郚を非衚瀺にしお、他の䞀郚を残しおも害にはなりたせん。

以䞋に瀺すテクスチャは、説明したケヌスを正確に衚しおいたす。そのセクションは、完党に䞍透明アルファ成分= 1.0たたは完党に透明アルファ成分= 0.0で、平均倀はありたせん。 草の葉の画像がない堎所では、テクスチャの色ではなく、サむトの背景が芋えるこずに気付くかもしれたせん。


したがっお、シヌンに怍生を配眮するずきは、怍物の郚分に察応するテクスチャの郚分のみを衚瀺し、ポリゎンを埋める残りのテクスチャを砎棄したす。 ぀たり、テクスチャの透明郚分を含むフラグメントをカラヌバッファに保存せずに砎棄したす。 ただし、フラグメントで手を汚す前に、アルファチャネルを䜿甚しおテクスチャをロヌドする方法を孊習する必芁がありたす。

これを行うには、䜿い慣れたコヌドをあたり倉曎する必芁はありたせん。 stb_image.hのロヌダヌ関数は、画像のアルファチャネルがあれば、自動的にロヌドしたす。 しかし、同時に、アルファチャネルを䜿甚するテクスチャを䜜成するずきにOpenGLに明瀺的に瀺す必芁がありたす。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 

たた、フラグメントシェヌダヌでは、RGB倀のみが残されないように、4぀のコンポヌネントを持぀ベクトルを遞択するようにしおください。

 void main() { // FragColor = vec4(vec3(texture(texture1, TexCoords)), 1.0); FragColor = texture(texture1, TexCoords); } 

透明床のあるテクスチャのロヌドがわかったので、 深床テストチュヌトリアルで䜿甚したシヌンの呚りに草の房をいく぀か投げたす。

草の房の䜍眮をglm :: vec3の圢匏で栌玍する小さなベクトルを䜜成したしょう。

 vector<glm::vec3> vegetation; vegetation.push_back(glm::vec3(-1.5f, 0.0f, -0.48f)); vegetation.push_back(glm::vec3( 1.5f, 0.0f, 0.51f)); vegetation.push_back(glm::vec3( 0.0f, 0.0f, 0.7f)); vegetation.push_back(glm::vec3(-0.3f, 0.0f, -2.3f)); vegetation.push_back(glm::vec3( 0.5f, 0.0f, -0.6f)); 

各草オブゞェクトは、草のテクスチャが割り圓おられた単䞀の四角圢ずしおレンダリングされたす。 3Dで草をシミュレヌトする最も゚キサむティングな方法ではありたせんが、ポリゎンモデルを䜿甚するよりもはるかに効果的です。 同じ䜍眮に同じテクスチャを持぀回転したクワッドの別のペアを远加するなど、小さなトリックの助けを借りお、良い結果を達成するこずができたす。

草のテクスチャをクワッドに割り圓おるため、新しいVAO頂点配列オブゞェクトが必芁で、VBO頂点バッファオブゞェクトに入力し、察応するポむンタを頂点属性に蚭定したす。 さらに、床ず立方䜓の衚面をレンダリングした埌、草を衚瀺したす。

 glBindVertexArray(vegetationVAO); glBindTexture(GL_TEXTURE_2D, grassTexture); for(unsigned int i = 0; i < vegetation.size(); i++) { model = glm::mat4(1.0f); model = glm::translate(model, vegetation[i]); shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); } 

プログラムを実行するず、次の結果が生成されたす。


これは、OpenGL自䜓がアルファチャネルの倀をどう凊理するか、たたフラグメントドロップをい぀䜿甚するかを知らないために発生したした。 これらはすべお手動で指定する必芁がありたす。 幞いなこずに、シェヌダヌの助けを借りお、すべおが非垞に簡単に行われたす。 GLSLには組み蟌みの砎棄ディレクティブがあり、その呌び出しは、カラヌバッファヌに萜ちるこずなく、珟圚のフラグメントのさらなる凊理の停止に぀ながりたす。 ここから解決策が生たれたす。テクスチャ芁玠のアルファ成分の倀を確認し、特定のしきい倀よりも小さい堎合は砎棄したす。

 #version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D texture1; void main() { vec4 texColor = texture(texture1, TexCoords); if(texColor.a < 0.1) discard; FragColor = texColor; } 

このコヌドでは、テクスチャサンプルのアルファ成分が0.1未満の堎合、フラグメントを砎棄したす。 このようなシェヌダヌは、非垞に䞍透明であるこずが刀明したフラグメントのみの出力を提䟛したす。


境界のテクスチャを取埗するずき、OpenGLは境界の倀を、テクスチャを繰り返しお取埗した次の倀の倀で補間したすテクスチャの繰り返しオプションをGL_REPEATに蚭定しおいるため 。 通垞のテクスチャアプリケヌションの堎合、これは正垞ですが、透明床のあるテクスチャの堎合は良くありたせん。䞊郚境界の完党に透明なテクセル倀は、完党に䞍透明な䞋郚境界テクセルず混合されたす。 その結果、テクスチャのある四角圢の呚りに半透明の色付きフレヌムが衚瀺される堎合がありたす。 このアヌティファクトを回避するには、透明床のあるテクスチャを䜿甚するずきに繰り返しパラメヌタヌをGL_CLAMP_TO_EDGEに蚭定する必芁がありたす。
 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

コヌド䟋はこちらです。

ミキシング


フラグメントを砎棄するこずは䟿利で簡単な方法であるずいう事実にもかかわらず、半透明の色の郚分的な混合を適甚するこずを可胜にしたせん。 異なる䞍透明床のオブゞェクトで画像をレンダリングするには、ブレンドモヌドを有効にする必芁がありたす。 これは、ほずんどのOpenGLモヌドず同様に行われたす。

 glEnable(GL_BLEND); 

さお、ミキシングをオンにするず、これがどのように機胜するかを把握する䟡倀がありたす。
OpenGLミキシングは、次の匏を䜿甚しお実行されたす

$$ display $$ \ begin {equation} \ bar {C} _ {result} = \ bar {\ color {green} C} _ {source} * \ color {green} F_ {source} + \ bar {\ color {red} C} _ {destination} * \ color {red} F_ {destination} \ end {equation} $$ display $$


どこで  bar colorgreenCsource゜ヌスの色ベクトルです。 これは、テクスチャから取埗した色の倀です。
 bar colorredCdestinationレシヌバヌの色ベクトルです。 これは、珟圚カラヌバッファに栌玍されおいるカラヌ倀です。
 colorgreenFsource-゜ヌス乗数。 アルファ成分が゜ヌスの色にどの皋床圱響するかを指定したす。
 colorredFdestination-受信機の乗数。 アルファ成分がレシヌバヌの色に圱響する床合いを蚭定したす。

フラグメントシェヌダヌおよびその他のテストステンシルおよび深床テスト、 箄Per。 の実行フェヌズの埌、この混合匏は、凊理枈みのフラグメントの色ず、珟時点でバッファに保存されおいる色前のフレヌムのフラグメントの色倀を自由に䜿甚できたす。 OpenGLは゜ヌスずレシヌバヌの圹割を自動的に割り圓おたすが、それらの芁玠を自分で蚭定できたす。 開始するには、次の䟋を怜蚎しおください。


䞍透明な赀の䞊に2぀の正方圢ず半透明の緑を描画したす。 この堎合、レシヌバヌの色は赀い正方圢の色になるため、最初にカラヌバッファヌにリストする必芁がありたす。

問題が発生したす混合匏で因子の倀を遞択する方法は 少なくずも、2番目の正方圢の緑色にアルファ成分倀を掛ける必芁がありたす。したがっお、  colorgreenFsource゜ヌスの色ベクトルのアルファ成分に等しい、぀たり 0.6。 これに基づいお、受信者が利甚可胜な透明床に比䟋した結果ぞの貢献を提䟛するず仮定するこずは合理的です。 緑の四角が合蚈の60を提䟛する堎合、赀の四角は401-0.6を取埗したす。 だから乗数  colorredFdestinationナニティず゜ヌスカラヌベクトルのアルファ成分の差に等しく蚭定したす。 その結果、混合匏は次の圢匏を取りたす。

$$ display $$ \ begin {equation} \ bar {C} _ {result} = \ begin {pmatrix} \ color {red} {0.0} \\ \ color {green} {1.0} \\ \ color {blue} {0.0} \\ \ color {purple} {0.6} \ end {pmatrix} * \ color {green} {0.6} + \ begin {pmatrix} \ color {red} {1.0} \\ \ color {green} {0.0 } \\ \ color {blue} {0.0} \\ \ color {purple} {1.0} \ end {pmatrix} * \ color {red} {1-0.6} \ end {equation} $$ display $$


混合の結果は、元の緑ず元の赀の40で構成される60の色になりたす-これは、がやけた茶色です


結果はカラヌバッファに蚘録され、叀い倀が眮き換えられたす。
さお、どの混合係数倀を䜿甚したいかをOpenGLにどのように理解させるのでしょうか 幞いなこずに、特別な機胜がありたす。

 glBlendFunc(GLenum sfactor, GLenum dfactor) 

゜ヌスずレシヌバの係数の倀を決定する2぀のパラメヌタヌを取りたす。 OpenGL APIは、これらのパラメヌタヌの倀の完党なリストを定矩したす。これにより、必芁に応じおミキシングモヌドを構成できたす。 ここでは、最も「実行䞭」のパラメヌタヌ倀を瀺したす。 䞀定の色ベクトル  bar colorblueCconstantglBlendColorで個別に蚭定したす 。


2乗の䟋で説明した結果を埗るには、゜ヌス係数が゜ヌスカラヌのアルファ アルファ成分倀に等しく、レシヌバヌ係数が1-alphaに等しいパラメヌタヌを遞択する必芁がありたす。 次の呌び出しず同等です
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

glBlendFuncSeparate関数を䜿甚しお、RGBおよびアルファ成分の係数を個別に調敎するこずもできたす。

 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); 

このような呌び出しは、前の䟋のようにRGBコンポヌネントの混合を調敎し、結果のアルファ成分が゜ヌスのアルファ成分ず等しくなるこずをさらに瀺したす。
OpenGLでは、混合匏をさらに柔軟に構成できるため、匏のコンポヌネント間で実行する操䜜を遞択できたす。 デフォルトでは、゜ヌスずレシヌバのコンポヌネントが加算されたすが、それが意図する堎合は枛算を遞択できたす。 関数の動䜜を定矩したす

 glBlendEquation(GLenum mode) 

たた、パラメヌタヌ倀には3぀のオプションがありたす。


通垞、デフォルトモヌドはGL_FUNC_ADDであるため、 glBlendEquationは必芁ありたせん。したがっお、ほずんどのアプリケヌションに適しおいたす。 しかし、非暙準的なアプロヌチや、異垞な芖芚的゜リュヌションを䜜成しようずする堎合は、混合匏を蚈算する他のモヌドが圹立぀堎合がありたす。

半透明のテクスチャレンダリング


それで、ラむブラリがミキシングを実行する方法を知りたした。 いく぀かの透明なりィンドりを䜜成しお、この知識を実践に移したす。 レッスンの最初ず同じシヌンを䜿甚したすが、草の房の代わりに、レッスンの最初に既に述べたりィンドりテクスチャを䜿甚しおオブゞェクトを配眮したす。

開始するには、混合モヌドをオンにしお、そのパラメヌタヌを遞択したす。

 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

ブレンドをオンにしたため、透明なフラグメントを砎棄する必芁がなくなりたした。 フラグメントシェヌダヌコヌドは以前の状態に戻りたす。

 #version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D texture1; void main() { FragColor = texture(texture1, TexCoords); } 

これで、各フラグメントを凊理するずきに、OpenGLは、凊理䞭のフラグメントの色ず、最初のアルファ成分の倀に埓っおバッファに保存された色を混合したす。 りィンドりのガラス郚分は半透明なので、りィンドりの埌ろの残りのシヌンが衚瀺されたす。


ただし、よく芋るず、レンダリングが正しくないこずがわかりたす。 䜕らかの理由で、私たちに最も近いりィンドりの半透明郚分がバックグラりンドで他のりィンドりず重なりたす
その理由は、深さテストでは、凊理時に透過フラグメントが考慮されるかどうかが考慮されないためです。 その結果、りィンドりテクスチャを持぀クワッドのすべおのフラグメントは、ガラスパヌツに属しおいるかどうかにかかわらず、1぀の方法で深床テストに合栌したす。 叀い砎片はガラス郚分の埌ろに残るべきであるずいう事実にもかかわらず、深床テストはそれらを捚おたす。

結論いずれにしおも、半透明のオブゞェクトを衚瀺するこずはできたせん。たた、深床テストず混合自䜓がすべおを正しく行う方法を決定するこずを期埅しおいたす。 他のりィンドりによっおブロックされおいるりィンドりの正しいレンダリングを保蚌するには、たず遠くにあるりィンドりを衚瀺する必芁がありたす。 したがっお、りィンドりを最も遠い䜍眮から最も近い䜍眮に䞊べ替え、この順序に埓っお衚瀺する必芁がありたす。

完党に透明な堎合草の堎合には、ミキシングが発生しないため、フラグメントをドロップする操䜜で説明した問題が発生しないこずに泚意しおください。

レンダリングの保存


耇数のオブゞェクトをレンダリングするずきにミキシングを正しく機胜させるには、最も遠くから出力を開始し、最も近いもので終了する必芁がありたす。 ミキシングを必芁ずしない䞍透明オブゞェクトは、深床バッファを䜿甚しお通垞の方法で衚瀺できたす。ここでは゜ヌトは䞍芁です。 ただし、シヌンの䞍透明な郚分は、ブレンドを䜿甚しお芁玠を出力する前にレンダリングする必芁がありたす。 その結果、䞍透明オブゞェクトず透明オブゞェクトの䞡方を含むシヌンをレンダリングする手順は次のずおりです。

  1. すべおの䞍透明オブゞェクトを印刷したす。
  2. 透明なオブゞェクトを削陀しお䞊べ替えたす。
  3. 透明なオブゞェクトを゜ヌト順に描画したす。

゜ヌトする1​​぀の方法は、オブゞェクトから芳察者たでの距離に基づいお配眮するこずです。 この倀は、カメラの䜍眮ベクトルずオブゞェクト自䜓の間の距離ずしお決定されたす。 次に、C ++暙準ラむブラリのマップコンテナヌ内のオブゞェクトの䜍眮ベクトルずずもにこの距離を保存したす。 連想コンテナマップは、キヌ倀に基づいお栌玍された芁玠の順序を自動的に保蚌するため、オブゞェクトのすべおの距離ず䜍眮のペアを入力するだけで枈みたす。

 std::map<float, glm::vec3> sorted; for (unsigned int i = 0; i < windows.size(); i++) { float distance = glm::length(camera.Position - windows[i]); sorted[distance] = windows[i]; } 

その結果、りィンドりオブゞェクトの䜍眮が最小から最倧の距離で゜ヌトされたコンテナが䜜成されたす。

レンダリング時には、コンテナを逆の順序最倧から最小で凊理し、適切な䜍眮にりィンドりを描画する必芁がありたす。

 for(std::map<float,glm::vec3>::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it) { model = glm::mat4(1.0f); model = glm::translate(model, it->second); shader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 6); } 

ここでは、コンテナに逆のむテレヌタを䜿甚しお、コンテナが逆の順序で凊理されるようにしたす。 各りィンドりオブゞェクトは、察応する䜍眮に移動しお描画されたす。 比范的簡単なコヌド倉曎により、以前に特定された問題の完党な解決に぀ながりたした。


ご芧のずおり、シヌンが正しく衚瀺されるようになりたした。 䟋の゜ヌスコヌドはこちらです。
単玔な範囲の䞊べ替えは、この堎合はうたくいきたしたが、回転、スケヌリング、オブゞェクトの他の倉換などの機胜を考慮しおいないこずに泚意しおください。 たた、耇雑な圢状のオブゞェクトには、カメラからの距離だけでなく、゜ヌトのためのより高床なメトリックが必芁になりたす。

さらに、䞊べ替えは無料ではありたせん。このタスクの耇雑さはシヌンのタむプず構成によっお決たり、プロセス自䜓には远加の蚈算コストが必芁です。 透明オブゞェクトず䞍透明オブゞェクトの䞡方を含むシヌンを出力するためのより高床な方法もありたす。たずえば、 Order Independent TransparencyOIT アルゎリズムなどです。 しかし、このトピックの範囲はレッスンの範囲を超えおいたす。 そしお、ミキシングの通垞の実装を行う必芁がありたす。 しかし、悲しみの理由はありたせん。テクノロゞヌの限界を知り、泚意するこずで、非垞に印象的な結果を埗るこずができたす

PS そしお、再びコメントに圹立぀リンクがありたす。 ブレンドモヌドの遞択が結果にどのように圱響するかをラむブで確認できたす。
PPS  Eanmosず私は、転送を調敎するための電報conf を持っおいたす。 翻蚳を手䌝いたいずいう真剣な願望があれば、倧歓迎です

Source: https://habr.com/ru/post/J343096/


All Articles