コンピューターの中央処理装置(CPU)とグラフィックス処理装置(GPU)は、コンピューターを使用するたびに相互作用して、鮮明で応答性の高いビジュアルインターフェイスを提供します。それらがどのように連携するかをよりよく理解するために読んでください。
写真提供 sskennel 。
今日の質疑応答セッションは、Q&AWebサイトのコミュニティ主導のグループであるStackExchangeの下位区分であるSuperUserの好意で行われます。
質問
スーパーユーザーリーダーのSathyaが質問を投げかけました。
ここでは、OpenGLAPIに基づく回転三角形を備えたTriangle.exeと呼ばれる小さなC ++プログラムのスクリーンショットを見ることができます。
確かに非常に基本的な例ですが、他のグラフィックカードの操作にも適用できると思います。
興味があったので、Windows XPでTriangle.exeをダブルクリックしてから、モニター上で三角形が回転しているのが見えるまでのプロセス全体を知りたいと思いました。 CPU(最初に.exeを処理する)とGPU(最終的に画面に三角形を出力する)はどのように相互作用しますか?
この回転する三角形の表示には、主に次のハードウェア/ソフトウェアが関係していると思います。
ハードウェア
- HDD
- システムメモリ(RAM)
- CPU
- ビデオメモリ
- GPU
- LCDディスプレイ
ソフトウェア
- オペレーティング・システム
- DirectX / OpenGL API
- Nvidiaドライバー
誰かがプロセスを説明できますか、おそらく説明のためのある種のフローチャートで説明できますか?
すべてのステップを網羅する複雑な説明(範囲を超えると思われる)ではなく、中級のIT担当者が従うことができる説明です。
ITプロフェッショナルと自称する人の多くは、このプロセスを正しく説明できなかったと確信しています。
答え
複数のコミュニティメンバーが質問に回答しましたが、Oliver Salzburgはさらに一歩進んで、詳細な回答だけでなく、優れたグラフィックを添えて回答しました。
JasonCによる画像、 ここで壁紙として利用可能 。
彼は書く:
プログラミングの側面と、コンポーネントが互いにどのように通信するかについて少し書くことにしました。多分それは特定の領域にいくらかの光を当てるでしょう。
プレゼンテーション
質問に投稿した単一の画像を画面に描画するには、何が必要ですか?
画面に三角形を描く方法はたくさんあります。簡単にするために、頂点バッファが使用されていないと仮定しましょう。 (A 頂点バッファ は座標を格納するメモリ領域です。)プログラムがグラフィックス処理パイプラインに、行内のすべての頂点(頂点は空間内の単なる座標)について単純に伝えたと仮定します。
だが 、何かを描く前に、まず足場を実行する必要があります。表示されます なぜ 後で:
//画面と深度バッファをクリアします glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //現在のModelviewマトリックスをリセットします glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //三角形を使用した描画 glBegin(GL_TRIANGLES); // 赤 glColor3f(1.0f、0.0f、0.0f); //三角形の上部(正面) glVertex3f(0.0f、1.0f、0.0f); // 緑 glColor3f(0.0f、1.0f、0.0f); //三角形の左側(正面) glVertex3f(-1.0f、-1.0f、1.0f); // 青 glColor3f(0.0f、0.0f、1.0f); //三角形の右側(正面) glVertex3f(1.0f、-1.0f、1.0f); //描画を完了 glEnd();
それで、それは何をしましたか?
グラフィックカードを使用するプログラムを作成するときは、通常、ドライバへの何らかのインターフェイスを選択します。ドライバーへのよく知られたインターフェースは次のとおりです。
- OpenGL
- Direct3D
- 奇跡
この例では、OpenGLを使用します。今、あなたの ドライバーへのインターフェース プログラムを作成するために必要なすべてのツールを提供するものです トーク グラフィックカード(またはドライバ、その後 話し合い カードに)。
このインターフェースはあなたに確実を与えるためにバインドされています ツール 。これらのツールは、 火 プログラムから呼び出すことができます。
そのAPIは、上記の例で使用されているものです。よく見てみましょう。
足場
実際に描画を行う前に、 セットアップ 。ビューポート(実際にレンダリングされる領域)、パースペクティブ( カメラ あなたの世界に)、あなたが使用するアンチエイリアシング(三角形のエッジを滑らかにするため)…
ただし、そのいずれについても検討しません。私たちはあなたがしなければならないことを覗き見します すべてのフレーム 。お気に入り:
画面をクリアする
グラフィックパイプラインは、フレームごとに画面をクリアするわけではありません。あなたはそれを言わなければならないでしょう。どうして?これが理由です:
画面をクリアしないと、単純に
ドローオーバー
それはすべてのフレームです。だから私たちは
glClear
とともに
GL_COLOR_BUFFER_BIT
セットする。他のビット(
GL_DEPTH_BUFFER_BIT
)OpenGLにクリアするように指示します
深さ
バッファ。このバッファは、どのピクセルが他のピクセルの前(または後ろ)にあるかを判別するために使用されます。
変換
変換は、すべての入力座標(三角形の頂点)を取得し、ModelView行列を適用する部分です。これは、 説明します どのように私たちの モデル (頂点)は、回転、スケーリング、および平行移動(移動)されます。
次に、射影行列を適用します。これにより、すべての座標が移動して、カメラに正しく向き合うようになります。
次に、ビューポートマトリックスを使用してもう一度変換します。これを行ってスケーリングします モデル 私たちのモニターのサイズに。これで、レンダリングの準備ができた頂点のセットができました。
少し後で変革に戻ります。
図
三角形を描くには、OpenGLに新しいものを開始するように指示するだけです。
三角形のリスト
電話で
glBegin
とともに
GL_TRIANGLES
絶え間ない。
あなたが描くことができる他の形もあります。のような
三角ストリップ
または
三角ファン
。これらは主に最適化であり、同じ量の三角形を描画するためにCPUとGPU間の通信が少なくて済みます。
その後、各三角形を構成する3つの頂点のセットのリストを提供できます。すべての三角形は3つの座標を使用します(3D空間にいるため)。さらに、私はまた提供します
色
頂点ごとに、
glColor3f
前
召命
glVertex3f
。
3つの頂点(三角形の3つの角)の間の陰影はOpenGLによって計算されます 自動的に 。ポリゴンの面全体の色を補間します。
インタラクション
さて、ウィンドウをクリックすると。アプリケーションは、キャプチャするだけで済みます ウィンドウメッセージ クリックの合図です。次に、プログラムで必要なアクションを実行できます。
これは たくさん 3Dシーンとの対話を開始したい場合は、さらに困難になります。
最初に、ユーザーがウィンドウをクリックしたピクセルを明確に知る必要があります。次に、 視点 考慮に入れて、マウスをクリックしてシーンに入るポイントから、光線の方向を計算できます。次に、シーン内にオブジェクトがあるかどうかを計算できます 交差する その光線で 。これで、ユーザーがオブジェクトをクリックしたかどうかがわかります。
では、どのように回転させますか?
変換
私は、一般的に適用される2つのタイプの変換を認識しています。
- マトリックスベースの変換
- 骨ベースの変換
違いは 骨格 シングルに影響を与える 頂点 。行列は常に、描画されたすべての頂点に同じように影響します。例を見てみましょう。
例
以前に、 単位行列 三角形を描く前に。単位行列は単に提供するものです の tらんsふぉrまちおん まったく。ですから、私が描くものは何でも、私の視点によってのみ影響を受けます。したがって、三角形はまったく回転しません。
今すぐ回転させたい場合は、(CPU上で)自分で計算を行い、単に呼び出すことができます
glVertex3f
と
その他
座標(回転します)。または、GPUにすべての作業を任せることもできます。
glRotatef
描く前に:
// Y軸上で三角形を回転しますglRotatef(amount、0.0f、1.0f、0.0f);
量
もちろん、これは単なる固定値です。あなたがしたい場合は
アニメーション
、追跡する必要があります
量
フレームごとに増やします。
それで、待ってください、以前のすべてのマトリックスの話はどうなりましたか?
この簡単な例では、行列を気にする必要はありません。単に電話します
glRotatef
そしてそれは私たちのためにすべての面倒を見ます。
glRotateの回転を生成します角度ベクトルxyzの周りの度。現在のマトリックス(を参照) glMatrixMode )に回転行列を掛け、その積を現在の行列に置き換えます。 glMultMatrix 次の行列を引数として呼び出されました。x21– c + cxy1– c –zsxz1– c + ys0yx1– c + zsy21– c +cyz 1 – c –xs0xz1– c –ysyz1– c + xsz21– c + c 0 0 0 0 1
さて、ありがとう!
結論
明らかになるのは、たくさんの話があるということです と OpenGL。しかし、それは伝えていません 我ら 何でも。コミュニケーションはどこにありますか?
この例でOpenGLが私たちに伝えているのは 終わったら 。すべての操作には一定の時間がかかります。信じられないほど時間がかかる操作もあれば、信じられないほど速い操作もあります。
頂点を送信する GPUへの接続は非常に高速になるため、表現方法すらわかりません。 CPUからGPUに、すべてのフレームで数千の頂点を送信することは、ほとんどの場合、まったく問題ありません。
画面をクリアする ビューポートの大きさにもよりますが、1ミリ秒以下かかる場合があります(通常、各フレームの描画には約16ミリ秒しかかかりません)。それをクリアするには、OpenGLはクリアしたい色ですべてのピクセルを描画する必要があります。これは数百万ピクセルになる可能性があります。
それ以外は、グラフィックアダプタの機能(最大解像度、最大アンチエイリアシング、最大色深度など)についてOpenGLに尋ねることしかできません。
ただし、それぞれが特定の色を持つピクセルでテクスチャを塗りつぶすこともできます。したがって、各ピクセルは値を保持し、テクスチャはデータで満たされた巨大な「ファイル」です。これをグラフィックカードにロードして(テクスチャバッファを作成することにより)、次に シェーダー 、シェーダーにテクスチャを入力として使用し、「ファイル」に対して非常に重い計算を実行するように指示します。
次に、計算結果を(新しい色の形で)新しいテクスチャに「レンダリング」できます。
これが、GPUを他の方法で機能させる方法です。 CUDAはその側面と同様に機能すると思いますが、それを使用する機会はありませんでした。
主題全体に少しだけ触れました。 3Dグラフィックプログラミングは獣の地獄です。
説明に追加するものがありますか?コメントで音を立ててください。他の技術に精通したStackExchangeユーザーからの回答をもっと読みたいですか? ここで完全なディスカッションスレッドをチェックしてください 。