2010-02-11 64 views
3

我正在構建一個使用OpenGL的第一人稱射擊遊戲,並且我試圖讓槍模在鏡頭前浮動。我使用資源反編譯器(轉換爲.obj並加載)從Fallout 3中撕掉了一個模型。在OpenGL中構建一個FPS:我的槍正在被裁剪成截錐體

然而,這是它看起來像在屏幕上:

Screenshot

半槍的三角形剪裁到似乎是圓臺。

我把它放在我的鏡頭前是這樣的:

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); 

是否有任何方法可以關閉剪裁只槍?其他遊戲如何做到這一點?

在此先感謝。

+0

戀戀使用glu_teapot還有隊友:) – 2010-02-12 13:14:55

+0

其實這就是猶他茶壺我已經有一段時間了的高分辨率版本。它使用我自己的.obj加載器加載。 :) – knight666 2010-02-16 15:39:35

回答

2

從OpenGL的角度來看(無雙關語),frustrum只是另一個矩陣。你應該能夠推動投影矩陣,調用gluPerspective(或者如果你喜歡冒險的話,可以使用glFrustrum),將Znear設置爲非常小的值,繪製槍,然後彈出投影矩陣並繪製場景的其餘部分(小心,然而,投影矩陣堆棧通常很淺 - 它可能只有兩層)。

一個警告:我從來沒有真正想過這將如何影響z戰鬥。它可能沒有任何真正的好處 - 它可以像在繪製整個場景時具有較小的znear值一樣工作。

+0

我自己想出來了,但是事實證明這是解決方案。我將gluPerspective設置爲不同的值(30視野,0.0001的焦距),渲染了我的模型並恢復了舊視角。作品相當不錯! – knight666 2010-02-11 21:27:44

2

該問題是由近剪裁平面造成的。

減少用於計算投影矩陣的znear值。儘管如此,只是儘可能低。它越低,你會得到更多的z戰鬥問題。

+0

嗯。不需要。我必須將znear設置爲非常低(0.0001),以便不夾槍,然後在更復雜的場景中獲得巨大的z戰鬥問題。 – knight666 2010-02-11 14:17:07

2

您是否嘗試將槍進一步推入場景(即:遠離相機)?當你這樣做時,多邊形是否仍然被裁剪?如果不是,那麼,正如所建議的,您的模型正在被近裁剪位置(在您的投影矩陣中設置)剪裁。如果你仍然有文物,這個問題可能是來自渲染狀態,模型加載等的其他問題。

你在某個查看器中看到過整個模型嗎?也許這就是模型的外觀和聚合計數被優化的原因,因爲你需要在遊戲中看到這些多邊形

+0

當我將槍進一步推入場景(Z = -0.1而不是-0.0001)時,槍不再被夾住。只有當槍靠近相機時纔會出現問題。 – knight666 2010-02-11 15:14:24

+1

那麼,你有它,問題解決了!它被近平面夾住。 0.0001瘋狂地靠近相機,你的單位是什麼?對於fps,1 = 1m是常見的。但是,如果您使用不同的單位左右分割資產,則永遠不會有任何連貫性。另外,爲了讓它看起來更接近相機,也許你想要一個不同的視野。再次,70-90度是典型的fps。 – 2010-02-11 20:00:04

0

爲什麼不把槍推到更遠的地方並且將其放大以便它不會夾住近平面?

0

當您渲染近距離物體時,您必須指定一個不同的近遠剪取物平面,例如由角色持有的武器。這會導致片段的窗口空間深度值相對於其他場景元素無效,因此您還必須通過調用glDepthRange來修改目標深度範圍。這會提高相機附近物體的精度。如上所述,只修改您的一般場景平截頭體的近遠平面不是解決方案,也不是將槍向前/向後移動,因爲它們引入了z戰鬥問題。

0

由於不同層之間的深度值不在同一個「空間」,因此如果您不小心,使用不同投影矩陣的「分層」可能很危險。這裏我稱之爲一個圖層的是一組使用給定投影矩陣呈現的對象。通常有2個解決這個:

  1. 渲染您的不同層(對他們所有的對象)從最遠啓動並清除深度緩存之間的每個渲染。
  2. 使用glDepthRange爲圖層之間的深度緩衝區分區。

注意,在使用這些技術將允許你這樣修復與來自不同層一起作戰對象的潛在問題,但也有一些缺點:

  1. 它防止彼此相交的對象(近層將始終出現在更多圖層的頂部 - 它們不會相交)。有時候,你希望用fps來實現這一點,其中槍總是處於最佳狀態
  2. 你的深度緩衝區對於像postfx(景深等等)或延遲渲染的東西是不可用的。