在OpenGL中构建一个FPS:我的枪被截断在平截头体上

时间:2010-02-11 13:11:08

标签: c++ opengl frame-rate

我正在使用OpenGL构建第一人称射击游戏,而我正试图让一个枪模漂浮在相机前面。我使用资源反编译器(转换为.obj并加载)从辐射3中扯掉了一个模型。

然而,这就是它在屏幕上的样子:

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

有没有办法关闭枪的剪裁?其他游戏如何做到这一点?

提前致谢。

6 个答案:

答案 0 :(得分:2)

问题是由近剪裁平面引起的。

减少用于计算投影矩阵的znear值。只是尽可能低。它越低,你得到的z-fighting问题就越多。

答案 1 :(得分:2)

您是否尝试将枪进一步推入场景(即:远离相机)?当你这样做时,多边形是否仍然被剪裁?如果不是,则表示您的模型被近剪裁位置(在投影矩阵中设置)剪裁。如果你仍然有工件,问题可能是渲染状态,模型加载等等。

您是否在某些观众中看过整个模特?也许这就是模型的外观和聚合计数的优化,因为你需要在游戏中看到那些多边形

答案 2 :(得分:2)

从OpenGL的角度来看(没有双关语),frustrum只是另一个矩阵。您应该能够推动投影矩阵,调用gluPerspective(或glFrustrum,如果您喜欢冒险)将znear设置为非常小的值,绘制枪,然后弹出投影矩阵并绘制场景的其余部分(注意,然而,投影矩阵堆栈通常非常浅 - 它可以只有两个级别。)

有一点需要注意:我从未真正考虑过这会如何影响z战斗。它可能没有任何真正的好处 - 它可以像在绘制整个场景时具有较小的znear值一样工作。

答案 3 :(得分:0)

为什么不直接将枪推入场景并将其放大以使其不会靠近近平面?

答案 4 :(得分:0)

渲染近距离物体时,必须指定不同的近远剪裁平面,例如角色持有的武器。这会导致碎片的窗口空间深度值相对于其他场景元素无效,因此您还必须通过调用glDepthRange来修改目标深度范围。这样可以提高物体附近相机的精确度。

正如你所提到的,只修改一般场景平截头体的近远平面不是解决方案,也不是向前/向后移动枪,因为它们引入了z战斗问题。

答案 5 :(得分:0)

如果您不小心,使用不同投影矩阵的“分层”可能会很危险,因为不同层之间的深度值不在同一“空间”中。我在这里称之为图层的是一组用给定投影矩阵渲染的对象。通常有两种解决方案:

  1. 从最远处开始渲染不同的图层(包含所有对象)并清除每个渲染之间的深度缓冲区。
  2. 使用glDepthRange在图层之间划分深度缓冲区。
  3. 请注意,使用这些技术中的任何一种都可以帮助您解决来自不同层的对象的潜在问题,但存在一些缺点:

    1. 它可以防止物体相互交叉(层附近总会出现在其他层的顶部 - 它们永远不会相交)。有时候,你希望用fps来实现这一点,而枪总是在所有东西之上
    2. 您的深度缓冲区将无法用于postfx(景深等)或延迟渲染等内容。