3

OpenGL でカメラをセットアップして、いくつかの点を 3 次元で表示しようとしています。これを実現するために、古い固定機能スタイル (glMatrixMode()、glTranslate など) を使用するのではなく、モデル ビュー プロジェクション マトリックスを自分でセットアップして頂点シェーダーで使用したいと考えています。正射図法で十分です。

これに関する多くのチュートリアルでは glm ライブラリを使用しているようですが、私は OpenGL にまったく慣れていないので、正しい方法で学び、その後サードパーティのライブラリを使用したいと考えています。さらに、ほとんどのチュートリアルでは、glMotionFunc() と glMouseFunc() を使用してカメラを空間に配置する方法について説明していません。

だから、サンプルコードと3Dでポイントを見る方法のガイダンスを探していると思います。私が書いた頂点シェーダーは次のとおりです。

const GLchar *vertex_shader =   // Vertex Shader
"#version 330\n"
"layout (location = 0) in vec4 in_position;"
"layout (location = 1) in vec4 in_color;"
"uniform float myPointSize;"
"uniform mat4 myMVP;"
"out vec4 color;"  
"void main()"  
"{"
"   color = in_color;"
"   gl_Position = in_position * myMVP;"
"   gl_PointSize = myPointSize;"
"}\0";

MVP の初期値を、シェーダーの設定方法で単位行列になるように設定しました。これにより、ポイントの正しい 2D 表現が得られます。

// Set up initial values for uniform variables
glUseProgram(shader_program);

location_pointSize = glGetUniformLocation(shader_program, "myPointSize");
glUniform1f(location_pointSize, 25.0f);

location_mvp = glGetUniformLocation(shader_program, "myMVP");
float mvp_array[16] = {1.0f, 0.0f, 0.0f, 0.0f,  // 1st column
                       0.0f, 1.0f, 0.0f, 0.0f,  // 2nd column
                       0.0f, 0.0f, 1.0f, 0.0f,  // 3rd column
                       0.0f, 0.0f, 0.0f, 1.0f   // 4th column
                      };
glUniformMatrix4fv(location_mvp, 1, GL_FALSE, mvp_array);

glUseProgram(0);

ここで私の質問は、「モーション」と「マウス」の 2 つの関数をどのように適応させるかです。この時点では、これを行う非推奨のスタイルが使用された前の例のコードしかありません。

// OLD, UNUSED VARIABLES
int mouse_old_x;
int mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0;
float rotate_y = 0.0;
float translate_z = -3.0;

...
// set view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, translate_z);
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
...

// OLD, UNUSED FUNCTIONS
void mouse(int button, int state, int x, int y)
{
    if (state == GLUT_DOWN)
    {
        mouse_buttons |= 1<<button;
    }
    else if (state == GLUT_UP)
    {
        mouse_buttons = 0;
    }

    mouse_old_x = x;
    mouse_old_y = y;
}

void motion(int x, int y)
{
    float dx, dy;
    dx = (float)(x - mouse_old_x);
    dy = (float)(y - mouse_old_y);

    if (mouse_buttons & 1)
    {
        rotate_x += dy * 0.2f;
        rotate_y += dx * 0.2f;
    }
    else if (mouse_buttons & 4)
    {
        translate_z += dy * 0.01f;
    }

    mouse_old_x = x;
    mouse_old_y = y;
}
4

1 に答える 1

6

正しい方法で学習し、その後サードパーティのライブラリを使用したいと思います。

GLM は行列を処理するための単なる数学ライブラリであるため、GLM の使用に問題はありません。非常に基本的なことを学びたいということは非常に良いことです。最近ではめったに見られない特性。これらのことを知っていることは、高度な OpenGL を行う際に非常に役立ちます。

次の 3 つのことを学びましょう。

  1. 基本的な離散線形代数、つまり、離散要素を持つ行列とベクトルを処理する方法。当面は、スカラー要素と複雑な要素で十分です。

  2. ちょっとした数字。基本的な線形代数操作を実行するコードを記述できる必要があります。スケーリング、ベクトルの追加、ベクトルの内積と外積の実行。行列 - ベクトルおよび行列 - 行列の乗算を実行します。行列の反転。

  3. 同次座標について学びます。

( 4. 物事にスパイスを加えたい場合は、クォータニオンを学びましょう。それらはロックです!)

ステップ 3 の後、独自の線形数学コードを作成する準備が整います。同次座標についてまだ知らなくても。4×4 次元の行列と 4 次元のベクトルを効率的に扱うように書くだけです。

同次座標をマスターすると、OpenGL が実際に何をするかを理解できます。次に:独自の線形数学ライブラリを作成する際の最初のコーディング手順を省略します。なんで?バグだらけになるから。私が維持している 1 つの小さな linmath.h は、それらでいっぱいです。新しいプロジェクトで使用するたびに、それらのいくつかを修正します。したがって、GLM や Eigen など、十分にテストされたものを使用することをお勧めします。

MVP の初期値を、シェーダーの設定方法で単位行列になるように設定しました。これにより、ポイントの正しい 2D 表現が得られます。

これらをモデル、ビュー、プロジェクションの 3 つのマトリックスに分ける必要があります。シェーダーには、Modelview と Projection の 2 つが必要です。つまり、投影をそのままシェーダーに渡しますがModel · View = Modelview、別のユニフォームで渡された複合行列を計算します。

「カメラ」を移動するには、Viewマトリックスを変更します。

ここで私の質問は、「モーション」と「マウス」の 2 つの関数をどのように適応させるかです。この時点では、これを行う非推奨のスタイルが使用された前の例のコードしかありません。

OpenGL に触れていないため、このコードのほとんどは同じままです。置き換える必要があるのは、glRotate と glTranslate の呼び出しです。

すでに述べたように、あなたはViewマトリックスに取り組んでいます。まず、glRotate が何をするか見てみましょう。固定関数の OpenGL には内部エイリアスがありM、glMatrixMode で選択されたマトリックスに設定されます。次に、疑似コードで glRotate を次のように記述できます。

proc glRotate(angle, vec_x, vec_y, vec_z):
    mat4x4 R = make_rotation_matrix(angle, vec_x, vec_y, vec_z)
    M = M · R

さて、すべての魔法は function 内にあるようmake_rotation_matrixです。それがどのように見えるか。あなたは線形代数を学んでいるので、これはあなたにとって素晴らしい練習になります。R次のプロパティを持つ行列を見つけます。

l a = R·a、ここで、a は回転軸です

cos(phi) = b·c && b·a = 0 && b·c = 0、ここで、ファイは回転角です

おそらくこれをやりたいだけなので、OpenGL-1.1 仕様を調べることもできます。この仕様では、glRotatef に関するセクションでこのマトリックスが文書化されています。

glRotate OpenGL-2 仕様

それらのすぐ横に、他のすべての行列操作関数の仕様があります。

これで、glMatrixMode で選択した非表示の状態変数を操作する代わりに、行列数学ライブラリを、定義して提供した行列変数で直接操作できるようになります。あなたの場合View。同様に、Projectionand を使用しModelます。次に、レンダリングするときに、Model と View を前述のコンパウンドに縮小します。Modelview * positionこれは、(フラグメント シェーダーの場合)頂点位置をアイスペースに移動する中間結果が必要になることが多いためです。行列の値を決定したら、プログラム (glUseProgram) をバインドして均一な値を設定し、ジオメトリをレンダリングします。(glDraw…)

于 2013-01-05T14:47:01.947 に答える