2010-02-11 30 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(景深等等)或延迟渲染的东西是不可用的。