2009-10-28 3 views
16

私はOpenGL 2アプリケーションを書く経験が少しあり、OpenGL 3を使って学びたいと思っています。これについては、固定小冊子の廃止を説明するAddison Wesley "Red-book"と "Orange Book"(GLSL)新しいプログラマブルパイプライン(シェーダ)を提供します。しかし、私が把握できないのは、非推奨のtranslate *、rotate *とscale *関数を使用せずに、複数のオブジェクトを持つシーンを構築する方法です。OpenGL 3.xで単一オブジェクトをどのように翻訳するのですか?

OGL2で私がしていたことは、translateとrotate関数を使用して3D空間で「動き回る」ことでした。そして、glBegin ... glEndを使ってそれらのオブジェクトをローカル座標で作成しました。 OGL3では、これらの関数はすべて推奨されなくなりました。私が理解するように、シェーダに置き換えられました。しかし、私が作ったオブジェクトごとにシェーダプログラムを呼び出すことはできません。他のすべてのオブジェクトにも影響はありませんか?

私の問題については十分に説明しても分かりませんが、OpenGL 3.1のローカル座標で定義された複数のオブジェクトを持つシーンをプログラミングする方法が中心です。私が見つけたすべての初心者のチュートリアルでは、単一のオブジェクトを使用しているだけで、この問題は解決されていません。

編集:回転する2つの立方体が必要だと想像してください。これは、手動で各頂点座標を変更する痛みであり、モデルビュー行列を単純に変更することはできません。

答えて

20

まず基本的なことを考えてみましょう。

通常、次の手順を通して、あなたの地元の三角形の頂点を変換したい:標準GLでlocal-space coords-> world-space coords -> view-space coords -> clip-space coords

は、最初の2つの変換はGL_MODELVIEW_MATRIXを介して行われ、第三は、GL_PROJECTION_MATRIX

を介して行われます

これらのモデルビュー変換は、通常適用したい(変換、スケール、回転など)多くの興味深い変換に対して、で頂点を表現するときにベクトル - 行列乗算として表現できるようになります。通常、頂点V = (x, y, z)は、このシステムでは(x, y, z, 1)と表されます。

頂点V_localを平行移動し、次に回転させ、次に平行移動を行いたいとします。各変換は行列*で表すことができます。それらをT1、R1、T2と呼ぶことにしましょう。 各頂点に変換を適用したい:V_view = V_local * T1 * R1 * T2。行列乗算は連想的であり、我々はすべてのために一度だけ計算することができるM = T1 * R1 * T2

このようにして、Mを頂点プログラムに渡し、V_view = V_local * Mを計算すればよいだけです。最後に、典型的な頂点シェーダは、頂点位置を単一の行列で乗算します。その1つの行列を計算するすべての作業は、オブジェクトをローカル空間からクリップ空間に移動する方法です。

Ok ...多くの重要な詳細を見てみました。

まず、私が今まで説明したことは、通常はクリップ空間ではなく、ビュー空間までの変換を実際にカバーするだけです。しかし、ハードウェアは、頂点シェーダの出力位置がその特別なクリップ空間で表現されることを期待しています。重要な計算なしにクリップ空間座標を説明するのは難しいので、私はそれを残しておきますが、重要なのは、頂点をそのクリップ空間にもたらす変換は、通常、同じタイプの行列乗算として表現できるということです。これは古いgluPerspective、glFrustumとglOrthoが計算するものです。

第2に、これは頂点の位置に適用されます。法線を変換する数学は多少異なります。これは、法線を変換後に垂直に保ちたいからです(参考のために、一般的な場合はモデルビューの逆転置による乗算が必要ですが、多くの場合、単純化することができます)

第3に、4D座標を頂点シェーダに送ることはありません。一般に、3Dのものを渡します。 OpenGLは、頂点シェーダが余分な座標を追加する必要がないように、これらの3次元座標(または2-D、btw)を4-D座標に変換します。各頂点を拡大してwの座標として1を追加します。

だから、すべてのオブジェクトをまとめてまとめるには、オブジェクトに適用するすべての変換に基づいて、それらのマジックM行列を計算する必要があります。シェーダの内部では、各頂点の位置にその行列を掛けて頂点シェーダの位置出力に渡す必要があります。典型的なコードは、多かれ少なかれ(これは古い命名法を使用している)である。

mat4 MVP; 
gl_Position=MVP * gl_Vertex; 

*実際の行列は、特にこれらの各機能のmanページには、ウェブ上で発見することができます:rotatetranslatescaleperspectiveortho

+1

その非常にトーゴの答えをありがとう!私が見逃した詳細は、glDrawElementsの呼び出しの間にMVP行列を変更することができるということです()。これらの非常に一般的な行列の仕様をプログラマに残すためにkhronosから変わった動き。彼らはすぐにgluまたは同様の方法に彼らの方法を見つけることを願って... – Wonko

+0

これはミドルウェアのためです。 GL3.2は、高速コーディングにはあまり表現力がありません。しかし、以前のバージョンは、実際のアプリケーションでは抽象度が間違っていました。それには国家管理の枠組みが必要でした。 また、行列を保持したいとします。これは、ドライバがすべての行列スタックを保持しなければならないこと、それを必要とする_all_シェーダ(頂点だけではない)にそれらを渡す方法、M、MV、MVP、IT(MV)、IT )。最悪の部分?一度に多くの行列操作を実行することで、効率的に数学を行うことができる唯一のアプリケーションです。 GLはそれを効率的に行うことはできません。 – Bahbar

1

これらの関数は明らかに推奨されていませんが、技術的にはまだ完全に機能し、実際にコンパイルされます。したがって、translate3f(...)などの関数を使用することはできます。

ここで、this tutorialには、新しいシェーダの仕組みや空間内の複数のオブジェクトの良い説明があります。

頂点のx配列を作成し、それらをx VAOオブジェクトにバインドし、そこからシェーダなどを使ってシーンをレンダリングすることができます... meh、それを読みやすくするのは簡単です。新しい概念を把握する。

また、OpenGL 'Red Book'と呼ばれる新しいリリース - The Official Guide to Learning OpenGL, Versions 3.0 and 3.1があります。これには、「OpenGLの非推奨メカニズムについての議論と、OpenGLの将来のバージョンであなたのプログラムを検証する方法」が含まれています。

私はそれが援助の願いです!

+0

再びすばやく答えてくれてありがとう。私はあなたが言及したチュートリアルを読みましたが、彼は2つの三角形を作成しますが、彼はグローバル座標でそれらを作成します - 私が望むようにローカルではありません。問題は、より複雑なモデルがある場合、特にモデルが動く場合に、グローバル座標を使用するのが面倒になることがある場合です。また、.objファイルからpremadeオブジェクトを読み込み、3D空間のどこかに配置したいと考えています。 – Wonko

+8

@マーク最初のリンクが壊れています。 – Jeff

関連する問題