3

私は OpenGL を使用して一人称シューティング ゲームを構築しています。銃のモデルをカメラの前に浮かせようとしています。リソース逆コンパイラ (.obj に変換してロード) を使用して、Fallout 3 からモデルをリッピングしました。

ただし、画面上では次のように表示されます。

スクリーンショット

銃の三角形の半分は、円錐台と思われる部分にクリップされています。

こんな感じでカメラの前に置きました。

glPushMatrix();
    glLoadIdentity();

    glTranslatef(m_GunPos.x, m_GunPos.y, m_GunPos.z);
    glRotatef(m_GunRot.x, 1, 0, 0);
    glRotatef(m_GunRot.y, 0, 1, 0);
    glRotatef(m_GunRot.z, 0, 0, 1);
    glScalef(m_GunScale.x, m_GunScale.y, m_GunScale.z);

    m_Gun->Render(NULL);
glPopMatrix();

そこで、元のマトリックスを保存しGL_MODELVIEW、恒等マトリックスをロードし、銃をカメラの少し右側に移動してレンダリングします。これは、SceneNode のレンダリング ルーチンです。

glPushMatrix();
    if (m_Model) { m_Model->Render(&final); }

    if (m_Children.size() > 0)
    {
        for (std::vector<SceneNode*>::iterator i = m_Children.begin(); i != m_Children.end(); ++i)
        {
            (*i)->Render(&final);
        }
    }
glPopMatrix();

そのため、独自のモデルと子 SceneNode をレンダリングします。最後に、実際のメッシュ レンダリングは次のようになります。

if (m_Material)
{
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, m_Material->m_TexDiffuse);
}

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glVertexPointer(3, GL_FLOAT, sizeof(Vec3), &m_Vertex[0]);
glNormalPointer(GL_FLOAT, sizeof(Vec3), &m_Normal[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &m_UV[0]);

glDrawArrays(GL_TRIANGLES, 0, m_Vertex.size());

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

銃だけのクリッピングをオフにする方法はありますか? 他のゲームはどのようにこれを行うのですか?

前もって感謝します。

4

6 に答える 6

2

OpenGL の観点から (しゃれた意図はありません)、フラストラムは単なる別のマトリックスです。射影行列をプッシュし、gluPerspective (冒険好きなら glFrustrum) を呼び出して znear を非常に小さな値に設定し、銃を描画し、射影行列をポップしてシーンの残りを描画できるはずです (注意してください。ただし、射影行列のスタックは非常に浅いことが多く、2 レベル程度になることもあります)。

注意点が 1 つあります。これが Z ファイティングにどのように影響するかを考えたことはありません。それは実際には何の役にも立たないかもしれません。シーン全体を描画する際に znear 値が小さい場合と同じように機能する可能性があります。

于 2010-02-11T19:28:50.680 に答える
2

この問題は、ニア クリッピング プレーンが原因で発生します。

射影行列の計算に使用した znear 値を減らします。ただし、必要なだけ低くしてください。値が低いほど、Z ファイティングでより多くの問題が発生します。

于 2010-02-11T13:30:03.507 に答える
2

銃をシーンにさらに押し込んでみましたか (つまり、カメラから遠ざけましたか)? そうするとき、ポリゴンはまだ切り取られていますか? いいえの場合、提案されているように、モデルは近くのクリッピング場所 (射影行列で設定) によってクリッピングされています。それでもアーティファクトがある場合は、レンダー ステート、モデルの読み込みなどに問題がある可能性があります。

ビューアーでモデル全体を見たことがありますか? ゲーム内でこれらのポリゴンを表示する必要があるため、モデルの外観とポリゴン数が最適化されている可能性があります。

于 2010-02-11T15:05:13.740 に答える
0

キャラクターが持っている武器など、近くのオブジェクトをレンダリングする場合は、別のニア ファー クリップ プレーンを指定する必要があります。これにより、フラグメントのウィンドウ空間深度値が他のシーン要素に対して無効になるため、glDepthRange を呼び出してターゲット深度範囲を変更する必要もあります。これにより、オブジェクトの近くにあるカメラの精度が向上します。

あなたが言及したように、一般的なシーンの錐台の遠近面を変更するだけでは解決策ではなく、Z ファイティングの問題が発生するため、銃を前後に移動することもできません。

于 2010-02-11T21:06:39.063 に答える
0

ガンをシーンのさらに奥まで押し込んでスケールアップして、近くの面にクリップしないようにしないのはなぜですか?

于 2010-02-11T16:48:19.147 に答える
0

異なるレイヤー間の深度値は同じ「空間」にないため、注意しないと、異なる射影行列を使用した「レイヤー化」が危険になる可能性があります。ここでレイヤーと呼んでいるのは、特定の射影行列でレンダリングされたオブジェクトのグループです。通常、これには 2 つの解決策があります。

  1. 最も遠いものから始めて、各レンダリング間の深度バッファーをクリアしながら、さまざまなレイヤーを (その上にあるすべてのオブジェクトと共に) レンダリングします。
  2. glDepthRange を使用してレイヤー間の深度バッファーを分割します。

これらの手法のいずれかを使用すると、異なるレイヤーのオブジェクトが一緒に戦うという潜在的な問題を修正できることに注意してください。ただし、いくつかの欠点があります。

  1. オブジェクトが互いに交差するのを防ぎます (近くのレイヤーは常に他のレイヤーの上に表示されます - 交差することはありません)。とにかく、銃が常にすべての上にある fps で達成したいことがあります。
  2. 深度バッファーは、postfx (被写界深度など) や遅延レンダリングなどには使用できません。
于 2010-02-12T13:11:56.420 に答える