14. フレームバッファのラスタ化の方法と操作方法

14.010 OpenGL のフレームバッファに直接書き込むためのアドレスを取得するにはどうしたら良いですか?

OpenGLは、アプリケーションにframebufferのアドレスを得させるために、標準のメカニズムを提供しません。 もしインプリメンテーションがこれを許すならば、それは拡張です。

一般に、単本位制グラフィックスハードウェアフォーマット〈マイクロソフトWindowsの下のVGA標準などの〉のためのグラフィックスプログラムを書くプログラマーは、framebufferのアドレスを望みます。 プログラマーは、多種多様なグラフィックスハードウェア〈マイクロソフトWindowsと従ってに動かない多く〉において動くように、OpenGLがデザインされると解釈する必要があります どのような種類の標準のframebufferフォーマットでもサポートしない 。 たぶん、プログラマーが、この所有権を主張したframebufferレイアウトに不慣れなので、ライティングはそれに予測不可能な結果を直接引き起こします。 さらに、いくつかのOpenGL機器は、CPUがアドレスするかもしれないframebufferを持つことができません。

glReadPixels()コマンドによって色、深さ、および型板バッファの内容を読むことができます。 その上、glDrawPixels()とglCopyPixels()は、それへのイメージおよびBLTingされたイメージをまわりにOpenGLバッファに送ることで利用可能です。

14.015 glDrawPixels と glReadPixels はどのように使うのですか?

glDrawPixels()とglReadPixels()は矩形のエリアを書き、framebufferから、およびframebufferからそれぞれ読んで聞かせます。 また、フォーマットパラメータによって型板と深さバッファ情報にアクセスできます。 単一のピクセルは書かれうるか、または1の高さパラメータを指定することによって読まれます。

現在のラスタを持つglDrawPixels()引きピクセルデータは、左下コーナーに置きます。 ラスタポジションが間違って設定されるので、glDrawPixels()を使っている問題は、一般に起こります。 ラスタポジションがglRasterPos*()機能に設定される時には、まるでそれが3D頂点であるかのようにそれは変換されます。 そして、glDrawPixels()データは、結果として生じている機器同等ラスタポジションに書かれます。 (これは、ピクセル配列とビットマップデータを3Dスペースのポジションに縛ることを可能にします)。

ラスタポジションが眺めボリュームの外にある時には、それは刈り、glDrawPixels()呼び出しはされません。 glDrawPixels()データの一部が見える時にさえ、これは起こります。 ここには、ラスタポジションが切り取られる時にどのように与えるかの情報があります

glReadPixels()はラスタポジションを使いません。 代わりに、それは、それ(X、Y)の機器同等アドレスをその最初の2つのパラメータから得ます。 glDrawPixels()のように、読まれたエリアは、左下コーナーのためのxyを持っています。 問題は、ピクセル ならば を読む時に起こるかもしれません:

両方のglDrawPixels()とglReadPixels()のために心に留めてください

14.020 既存のウィンドウにおいて、ダブルバッファとシングルバッファのモードを切り替えるにはどうしたら良いですか?

もし単一緩衝されたウィンドウを作成するならば、それを交換できないでしょう

もし2倍緩衝されたウィンドウを作成するならば、glDrawBuffer()からGL_FRONTまでを設定し、スワップバッファ呼び出しをglFlush()呼び出しと交換することによって、それを、単一緩衝されたウィンドウとみなすことができるでしょう。 2倍緩衝されて、後ろ に に切り替えるために、glDrawBuffer()からGL_BACKまでを設定する必要があり、フレームの終わりでスワップバッファを呼びます。

14.030 フレームバッファから一つのピクセルの情報を読み取るにはどうしたら良いですか?

glReadPixels()を使い、高さパラメータでそれの値を通過してください

14.040 描かれたプリミティブの Z値を得るにはどうしたら良いですか?

呼び出しによって深さバッファから後ろにglReadPixels()にそれを読んでシングルピクセルの深さ価値を得ることができます。 これはスクリーンスペース深さ値を戻します。

オブジェクトにおいてこの価値にスペースを調整させることが有益であるかもしれません。 もしそうなら、gluUnProject()へのスクリーンスペース深さ値とともにウィンドウXとY値を通過する必要があります。 ここのgluUnProject()についてのより多くの情報を見てください

14.050 ステンシルバッファに描いたパターンを入れるにはどうしたら良いですか?

OpenGL状態を次の通り設定できます

glEnableです(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS、0x1、0x1);
glStencilOp(GL_REPLACE、GL_REPLACE、GL_REPLACE);

次の表現は、1ビットを、されたすべてのピクセルのための型板バッファに設定します

14.060 フロントバッファから、バックバッファへ、またはその逆へコピーするにはどうしたら良いですか?

glCopyPixels()を呼ぶ必要があります。 glCopyPixels()のソースと宛先は、呼び出しにglReadBuffer()とglDrawBuffer()にそれぞれ設定されます。 従って、後ろのバッファから前のバッファ、あなたにコピーすることはすることができます コード 以下 :

glReadBuffer(GL_BACK);
glDrawBuffer(GL_FRONT);
glCopyPixels(GL_COLOR);

14.070 ウィンドウの一部が他のウィンドウと重なっている場合、glReadPixels でその重なっている部分のピクセルデータがおかしいのはなぜですか?

これは、ピクセル所有権テストと呼ばれるOpenGL指定の部分に起因しています。 もしウィンドウが別のウィンドウによって覆い隠されるならば、それは、覆い隠された領域のために、ピクセルデータを蓄える必要がありません。 従って、glReadPixels()呼び出しによって、覆い隠された領域のための不確定なデータが戻ることができます。

ピクセル所有権テストは1つのOpenGLインプリメンテーションから次に変わります。 あるOpenGLインプリメンテーション店はウィンドウ、または全体のウィンドウの領域を画面外のバッファに覆い隠しました。 そのようなインプリメンテーションは、覆い隠されたウィンドウのための有効なピクセルデータを戻すことができます。 しかし、framebuffer記憶位置のために1対1のスクリーンの多くのOpenGLインプリメンテーションマップピクセルおよびウィンドウの覆い隠された領域のために、ピクセルデータを蓄えません(そして戻ることができません)。

1つの戦略が、windowingシステムに、ウィンドウスタックのトップにウィンドウを前面に出すのを指示する必要があり 与える 、そして、glReadPixels()呼び出しを実行します。 しかし、そのようなアプローチは、まだ、ソースウィンドウを覆い隠すことができるユーザー介入を危険にさらしています。

いくつかのアプリケーションのために働くことができるアプローチが、Xウィンドウの下のPixmapなどの不可視のウィンドウに与える必要があります。 このタイプの引いている表面は、ユーザーにより覆い隠されえず、その内容はいつもピクセル所有権テストに合格するべきです。 そのような引いている表面から読むことによりいつも有効なピクセルデータは産出されるべきです。 あいにく、そのような引いている表面に与えることはしばしばグラフィックスハードウェアによって促進されません。

14.080 異なる変換で見るとき、スムーズシェーディングされた四角形の外見が違うのはなぜですか?

OpenGLインプリメンテーションはクワタを表現のための2つの三角形に解体できないか、または解体できてはならないかもしれません。 それがそれを解体するかどうかは、どのように個々のscanlineを横切ってエッジと最終的に沿って色が改ざんされるかを決定します。

多くのOpenGLアプリケーションはそれらの固有のラスタ化問題のためクワタをまったく避けます。 クワタは、等しいクワタとしてかかった同じデータ通信によって2三角形GL_TRIANGLE_STRIPプリミティブとして容易にできます。 賢明なプログラマーはクワタの代わりにこのプリミティブを使います。

14.090 線の正確なピクセル化された情報はどうしたら得られますか?

OpenGL指定により様々なラインハードウェアが考慮されます。 従って、pixelizationを強要しなさい 全然可能ではないかもしれません

OpenGL指定を読み、ダイヤの出口規則に精通していて あなた自身 ようになりたいかもしれません。 この規則に精通していることにより、正確なpixelizationを得る最もよいチャンスが、あなたに与えられます。 しばらく、ダイヤの出口規則は、ダイヤモンド形のエリアが個々のピクセルに存在することを指定します。 もしそのラインの数学的な定義が、そのピクセル内で記入されたダイヤモンドを出るならば、ピクセルはラインによりrasterizedされます。

14.100 覆うか、留め継ぎにして広い線のエンドポイントをつけるにはどうしたら良いですか?

OpenGLは、複数のwidth-1コンポーネントラインを、お互いに隣接しているようにすることによって広いラインを引きます。 もし広いラインが大手のYであるならば、コンポーネントラインはXにおいてオフセットされます; もし広いラインが大手のXであるならば、コンポーネントラインはYにおいてオフセットされます。 これは、ラインセグメントの斜面に依存している明白な幅のラインセグメントと違いの接合で醜いギャップを生産できます。

共通の頂点を共有するラインに清潔に参加するためにOpenGLがメカニズムを提供しないこととそれに 清潔 キャップ末端 。

1つの可能な解決策が、正常なaliasedされたラインの代わりにスムーズ(antialiased)のラインをすることです。 クリーンな接合点を生み出すために、使用不可にされた深さテストまたはGL_ALWAYSに設定される深さ機能によってラインを引く必要があります。 詳細についてはantialiasedされるラインについての問題を見てください

別の解決は、ふたの取り付けと留め継ぎを処理するために、アプリケーションに向いています。 ラインの代わりに、アプリケーションはポリゴン顔において与える必要があります。 アプリケーションは、要求されたふたの取り付けおよび参加スタイルを提供するために頂点位置を計算するために、必要な数学を実行する必要があります。

14.110 ラバーバンド線を描くにはどうしたら良いですか?

この問題の無言の目的がであること、「そして、邪魔せずに、どのようにすることができるか 私 与え何か が、すでにされていたものを消去しますか?」。

ここには2回の共通のアプローチがあります

一方の方法は、オーバーレイ飛行機を使うことです。 ラバーバンドのラインをオーバーレイ飛行機に引き入れて、そして、オーバーレイ飛行機をきれいにします。 主要なframebufferの内容は妨害されません。 このアプローチの不利は、OpenGL機器がオーバーレイ飛行機を広くサポートしないことです。

他のアプローチは、可能であったロジックopによってXORモードに与えて、設定する必要があります。 もしRGBAウィンドウに与えているならば、コードは以下のように見える必要があります:

glEnableです(GL_COLOR_LOGIC_OP);
glLogicOp(GL_XOR);

絵の具を白にセットし、ラインをしてください。 ラインが引かれる所では、framebufferの内容は逆にされます。 二回目をラインに与える時には、framebufferの内容は復元されます。

RGBAウィンドウのためのロジックopコマンドはOpenGL1.1のため入手可能であるだけです。 1.0未満において、色インデックスウィンドウのロジックopを可能にすることができるだけで、() glEnableなので、GL_LOGIC_OPをパラメータ に として通過します。

14.120 塗りつぶしモードで四角形を描いて、その後ラインモードで四角形を描いた場合、なぜ線と四角形は同じピクセルに描かれないのですか?

満たされたプリミティブとラインプリミティブは、ラスタ化のための種々の規則に従います

満たされたプリミティブがされる時には、もしその正確なセンターがプリミティブの数学的な境界に入っているならば、ピクセルには触れるだけです

ラインプリミティブがrasterizedされる時には、理想的に、もしラインが、ピクセルの境界に記入されたダイヤモンドを出るならば、ピクセルには触れるだけです

これらの規則から、ラインループが、満たされたプリミティブのために使われたそれらが、ピクセルをrasterizeするかもしれないのと同じ頂点によって、満たされたプリミティブがしないことを指定したことがクリアであるはずです

OpenGL指定は、ダイヤの出口ラインラスタ化規則からのある逸脱を可能にするけれども、それはこのシナリオの違いを全然生じさせません。

14.130 スクリーンいっぱいの四角形を描くにはどうしたら良いですか?

変化セクションでこの問題を見てください

14.140 glClear()を呼ばずにバッファを初期化するかきれいにするにはどうしたら良いですか?

フルスクリーンクワタを引いてください変化セクションを見てください

14.150 線や多角形のアンチエイリアシングを働かせるためにはどうしたら良いですか?

スムーズ(antialiased)のラインをするために、アプリケーションが以下をする必要があります

glEnableです(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA);
glEnableです(GL_LINE_SMOOTH);

もし場面がスムーズなラインから完全に成っているならば、深さテストを使用不可にするか、またはそれをGL_ALWAYSに設定する必要があります

もし舞台面が両方のスムーズなラインおよび他の原始人を収容するならば、オフの回している深さテストはオプションではありません。 もしスムーズなラインを透明なプリミティブとみなすならば、ほとんど正しい表現結果を達成できるでしょう。 他の(不混合であった)プリミティブは、1番目を与えられるべきで、そして、スムーズなラインは前の注文への後ろでこの前与えました。 詳細については透明度セクションを見てください

これらの用心をすることによりさえ、共通の頂点を共有するスムーズなラインセグメントのジョイントでいくつかのラスタ化人工物は防止できません。 深さテストが可能であるという事実は多分、いくつかのライン末端を間違ってするかもしれません。 これは、スムーズなラインがされる間深さテストが可能でなければならないならばによって生きるために持っていてもよい人工物です。

すべてのOpenGLインプリメンテーション不サポートはポリゴンをantialiasedします。 OpenGLスペックによると、 GL_POLYGON_SMOOTHが可能な時には、インプリメンテーションは、aliasedされたポリゴンをできます。

14.160 フルシーンアンチエイシリアシングを行うにはどうしたら良いですか?

マルチパス蓄積バッファテクニックの記述のためにOpenGLプログラミングガイド、第3版、p452を見てください。 この方法は、ハードウェアにおいて蓄積バッファをサポートする機器をよく演奏します。

オプションの画像処理拡張をサポートするOpenGL1.2インプリメンテーションにおいて、すべすべさせているフィルタが最終的なframebufferイメージに適用できます

多くの機器はマルチサンプリング拡張をサポートします