プログラミングの側面と、コンポーネントが相互に通信する方法について少し書くことにしました。おそらく、特定の領域に光を当てるでしょう。
プレゼンテーション
質問に投稿した単一の画像を画面に表示するには、何が必要ですか?
画面に三角形を描くには多くの方法があります。簡単にするために、頂点バッファが使用されていないと仮定しましょう。(頂点バッファーは、座標を格納するメモリの領域です。)プログラムが、グラフィック処理パイプラインに、すべての単一の頂点(頂点は単なる空間内の座標)を連続して伝えたと仮定しましょう。
ただし、何かを描画する前に、まず足場を実行する必要があります。理由は後でわかります。
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Red
glColor3f(1.0f,0.0f,0.0f);
// Top Of Triangle (Front)
glVertex3f( 0.0f, 1.0f, 0.0f);
// Green
glColor3f(0.0f,1.0f,0.0f);
// Left Of Triangle (Front)
glVertex3f(-1.0f,-1.0f, 1.0f);
// Blue
glColor3f(0.0f,0.0f,1.0f);
// Right Of Triangle (Front)
glVertex3f( 1.0f,-1.0f, 1.0f);
// Done Drawing
glEnd();
それで、それは何をしましたか?
グラフィックカードを使用するプログラムを作成する場合、通常、ドライバーに対する何らかのインターフェイスを選択します。ドライバーへのよく知られたインターフェースは次のとおりです。
この例では、OpenGLを使用します。さて、あなたのドライバへのインターフェイスは、あなたのプログラムにするために必要なすべてのツール与えるものである話をグラフィックカード(または、ドライバーに話しカードにします)。
このインターフェイスは、特定のツールを提供します。これらのツールは、プログラムから呼び出すことができるAPIの形を取ります。
このAPIは、上記の例で使用されているものです。よく見てみましょう。
足場
実際に描画を行う前に、セットアップを実行する必要があります。ビューポート(実際にレンダリングされる領域)、視点(世界へのカメラ)、使用するアンチエイリアス(三角形のエッジを滑らかにするため)を定義する必要があります...
しかし、私たちはそれのどれも見ません。すべてのフレームでやらなければならないことをちょっと見てみましょう。好む:
画面をクリアする
グラフィックパイプラインは、すべてのフレームで画面をクリアするわけではありません。あなたはそれを言わなければなりません。どうして?これが理由です:
画面をクリアしない場合は、フレームごとに単純に描画します。それglClear
がGL_COLOR_BUFFER_BIT
セットで呼び出す理由です。もう1つのビット(GL_DEPTH_BUFFER_BIT
)は、深度バッファーをクリアするようOpenGLに指示します。このバッファーは、他のピクセルの前(または後ろ)にあるピクセルを判別するために使用されます。
変換
画像ソース
変換は、すべての入力座標(三角形の頂点)を取得してModelViewマトリックスを適用する部分です。これは、モデル(頂点)がどのように回転、拡大縮小、および移動(移動)されるかを説明するマトリックスです。
次に、射影行列を適用します。これにより、すべての座標が移動し、カメラに正しく向かいます。
次に、ビューポートマトリックスを使用してもう一度変換します。これを行って、モデルをモニターのサイズに合わせます。これで、レンダリングの準備ができた頂点のセットができました!
少し後で変換に戻ります。
図
三角形を描画するには、定数を使用して呼び出すことにより、三角形の新しいリストを開始するようにOpenGLに指示するだけです。描画できる他のフォームもあります。以下のような三角形ストリップや三角形ファン。これらは、同じ量の三角形を描画するためにCPUとGPU間の通信が少なくて済むため、主に最適化です。glBegin
GL_TRIANGLES
その後、各三角形を構成する3つの頂点のセットのリストを提供できます。すべての三角形は3つの座標を使用します(3D空間にいるため)。さらに、を呼び出す前に呼び出すことにより、各頂点の色も提供します。glColor3f
glVertex3f
3つの頂点(三角形の3つの角)間のシェードは、OpenGLによって自動的に計算されます。ポリゴンの面全体に色を補間します。
インタラクション
さて、ウィンドウをクリックすると。アプリケーションは、クリックを知らせるウィンドウメッセージをキャプチャするだけです。その後、プログラムで任意のアクションを実行できます。
これは、取得たくさんあなたがあなたの3Dシーンとの対話を開始したい、もう一度難しいです。
まず、ユーザーがウィンドウをクリックしたピクセルを明確に知る必要があります。次に、視点を考慮して、マウスクリックのポイントからシーンへの光線の方向を計算できます。その後、シーン内のオブジェクトがその光線と交差するかどうかを計算できます。これで、ユーザーがオブジェクトをクリックしたかどうかがわかりました。
それでは、どのように回転させるのですか?
変換
一般的に適用される2種類の変換を認識しています。
違いは、骨が単一の頂点に影響することです。行列は常に、描画されたすべての頂点に同じように影響します。例を見てみましょう。
例
前に、三角形を描く前に単位行列をロードしました。単位行列は、変換をまったく提供しないものです。だから、私が描くものは何でも、私の視点によってのみ影響を受けます。したがって、三角形はまったく回転しません。
今すぐ回転させたい場合は、自分で(CPU上で)計算を行い、単純glVertex3f
に他の座標(回転している)で呼び出すことができます。または、glRotatef
描画する前に呼び出すことで、GPUにすべての作業を任せることができます。
// Rotate The Triangle On The Y axis
glRotatef(amount,0.0f,1.0f,0.0f);
amount
もちろん、固定値です。あなたがしたい場合はアニメーション、あなたはを追跡する必要がありますamount
し、それをフレームごとに増加します。
さて、先ほどの行列の話はどうなりましたか?
この単純な例では、マトリックスを気にする必要はありません。私たちは単に電話をかけるだけでglRotatef
、それは私たちのすべての面倒を見てくれます。
glRotate
angle
ベクトルxyzを中心とした度数の回転を生成します。現在の行列(glMatrixModeを参照)は、現在の行列を置き換える積で回転行列を乗算します。これは、glMultMatrixが次の行列を引数として呼び出されたかのようになります。
x 21-c + cxy1-c-zsxz1-c + ys 0 yx1-c + zsy 21-c + cyz 1-c-xs 0 xz1-c-ysyz1-c + xsz 21-c + c 0 0 0 0 1
まあ、それをありがとう!
結論
明らかになるのは、OpenGL について多くの話があることです。しかし、それは私たちに何も語っていません。コミュニケーションはどこですか?
この例でOpenGLが伝えているのは、完了したときだけです。すべての操作には一定の時間がかかります。一部の操作には非常に時間がかかり、他の操作は非常に高速です。
GPUに頂点を送信するのは非常に高速で、表現方法もわかりません。CPUからGPUに、1フレームごとに数千の頂点を送信することは、ほとんどの場合、まったく問題ありません。
画面のクリアには、ビューポートの大きさに応じて、ミリ秒以上かかる場合があります(通常、各フレームを描画するのに約16ミリ秒しか時間がないことに注意してください)。それをクリアするために、OpenGLはクリアしたい色ですべてのピクセルを描画する必要があります。
それ以外は、グラフィックアダプターの機能(最大解像度、最大アンチエイリアス、最大色深度など)についてのみOpenGLに問い合わせることができます。
ただし、特定の色のピクセルでテクスチャを塗りつぶすこともできます。したがって、各ピクセルは値を保持し、テクスチャはデータで満たされた巨大な「ファイル」です。(テクスチャバッファを作成して)グラフィックカードにロードし、シェーダをロードして、そのシェーダにテクスチャを入力として使用し、「ファイル」に対して非常に重い計算を実行するように指示できます。
次に、計算の結果を(新しい色の形で)新しいテクスチャに「レンダリング」できます。
これが、GPUを他の方法で動作させる方法です。私はCUDAがその側面と同様に機能すると仮定しますが、私はそれを扱う機会がありませんでした。
私たちは本当に全体をほんの少しだけ触れました。3Dグラフィックプログラミングは、とんでもないことです。
画像ソース