0

OpenGL で球をレンダリングしようとしています。残念ながら、画面には常に背景しか表示されません。カメラの向きを変えてみましたが、うまくいきませんでした (間違っているかもしれませんが)。任意の洞察をいただければ幸いです。

画面を更新するために OpenGL が呼び出す関数は次のとおりです。

//The draw function - I have confirmed that this is called periodically.
void draw()
{
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glEnable(GL_CULL_FACE);
    glPolygonMode(GL_FRONT_AND_BACK, (globals.wireframe == true) ? GL_LINE : GL_FILL);

    glViewport(0, 0, globals.window_size.x, globals.window_size.y);

    mat4 prj = perspective(globals.fov, float(globals.window_size.x) / float(globals.window_size.y), globals.hither, globals.yon);
    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(value_ptr(prj));

    glMatrixMode(GL_MODELVIEW);
    mat4 context = mat4(1.0f);
    globals.ship.draw(context); //the ship only draws a sphere for now
    mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
    glLoadMatrixf(value_ptr(mv));

    glutSwapBuffers();
}

そして船の定義:

GLuint Ship::sphere_handle; //static
bool Ship::is_initialized; //static

mat4 Ship::draw(mat4 context) const {
    glLoadMatrixf(value_ptr(context));
    glCallList(sphere_handle);
    return context;
}

//called when program starts, after window created
bool Ship::initialize() {
    if (sphere_handle == BAD_GL_VALUE)
    {
        GLUquadric *q = gluNewQuadric();
        if (q != NULL)
        {
            if ((sphere_handle = glGenLists(1)) == 0)
            {
                cout << "Model::Initialize() - Failed to GenLists()" << endl;
                return false;
            }
            glNewList(sphere_handle, GL_COMPILE);
            gluSphere(q, 1.0, 10, 10);
            glEndList();
            gluDeleteQuadric(q);
            is_initialized = true;
        }
        else
        {
            return false;
        }
    }
    return true;
}
4

2 に答える 2

2

常に最初にチェックするのは、GL エラーがあるかどうかです。その場合は、原因を見つけて修正してください。

それ以外に、従来の GL での行列操作がどのように機能するかを誤解しているか、意図したとおりに記述していないことが原因のように見えるものがあります。draw()関数では、次のことを行います。

glMatrixMode(GL_MODELVIEW);
mat4 context = mat4(1.0f);
globals.ship.draw(context); //the ship only draws a sphere for now
mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
glLoadMatrixf(value_ptr(mv));

あなたが呼び出す3行目で

mat4 Ship::draw(mat4 context) const 
{
  glLoadMatrixf(value_ptr(context));
  glCallList(sphere_handle);
  return context;
}

ID をスタックの一番上にロードしてから、MODELVIEWを呼び出しますglCallList。この時点では、変換は必要ありません。つまり、概念的には、カメラは単位球の内側にあります。背面カリングにより、何も表示されません。実際に必要なのは、球体を 5.5 単位後方に移動して、球体の中心で直接 -Z を見下ろすようにすることです。

glMatrixMode(GL_MODELVIEW);
// load the view matrix FIRST! 
mat4 mv = lookAt(vec3(0.0f, 0.0f, -5.5f), vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
glLoadMatrixf(value_ptr(mv));
// draw the model with an indentity model-matrix - mind the changes to the function below!!
glPushMatrix(); // you don't want to mess up the view matrix for good
globals.ship.draw(mat4(1.0f));
glPopMatrix();

通話を並べ替えても問題ありません。Ship::draw()同様に変更する必要があります。まず、設計の観点から関数を改善できます。描画関数はモデル マトリックスをまったく変更しないし、変更すべきではないため、行列を値で取得せず、const 参照で取得します。第二に、ある時点で非同一モデル行列を使用する予定がある場合は、正しい行列乗算を適用する必要があります。関数が、渡されたモデル マトリックスのコピーを返す必要がある理由は、率直に言ってまったく理解できません。:) 私の提案は、次のように書き直すことです。

void Ship::draw(const mat4& context) const
{
  glMultMatrixf(value_ptr(context));
  glCallList(sphere_handle);
}

その後、もう1つやるべきことがあります。球体を +Z に沿って 5.5 単位移動します (つまり、カメラの視点を (0, 0, -5.5) に設定します)。球体を回転させないため、投影後にカメラが表示されることはなく、単に完全にクリップされます。おそらくあなたが望むのは、視点を (0, 0, 5.5) に設定することです。

別の注意点として、描画関数のさまざまな場所で不要なオーバーヘッドが発生します。

glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

これは非常にめったに変更されない状態であり、初期化時または本当に変更する必要がある場合にのみ呼び出す必要があります。レンダリング ループで呼び出すことは、ほとんど完全に不要です。

そうです

glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, (globals.wireframe == true) ? GL_LINE : GL_FILL);

ビューポートを変更するために、Qt や FreeGLUT などのウィンドウ フレームワークは特別なサイズ変更コールバックを提供します。そこに関数を配置し、そこに投影を更新します (寸法を変更すると、多くの場合、縦横比が変更されるため)。

編集: datenwolf の発言に注意して、従来の GL から離れてください。すでに GLM を使用している場合は、最新の OpenGL に一歩近づいています。:)

最新の OpenGL に関する膨大な情報については、Jason McKesson のチュートリアルと OpenGL.org のwikiを参照してください。

EDIT2 : 欠落しているプッシュ/ポップ ロジックを修正しました。

于 2013-09-13T10:18:06.460 に答える