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

所以它渲染自己的模型和任何子场景节点。最后,实际的网格渲染如下所示:

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

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

减少用于计算投影矩阵的 znear 值。只需将其设置为所需的最低值即可。它越低,z-fighting 的问题就越多。

于 2010-02-11T13:30:03.507 回答
2

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

您是否在某些查看器中看到了整个模型?也许这就是模型的外观并且优化了多边形数量,因为您需要在游戏中看到这些多边形

于 2010-02-11T15:05:13.740 回答
2

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

一个警告:我从来没有真正考虑过这应该如何影响z-fighting。它可能没有任何真正的好处——它的效果可能与您在绘制整个场景时具有较小的 znear 值相同。

于 2010-02-11T19:28:50.680 回答
0

为什么不把枪推到场景中更远的地方,然后按比例放大,这样它就不会夹在近平面上?

于 2010-02-11T16:48:19.147 回答
0

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

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

于 2010-02-11T21:06:39.063 回答
0

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

  1. 从最远的地方开始渲染不同的图层(上面有所有对象),并在每次渲染之间清除深度缓冲区。
  2. 使用 glDepthRange 对图层之间的深度缓冲区进行分区。

请注意,使用这些技术中的任何一种都可以解决来自不同层的对象一起战斗的潜在问题,但也有一些缺点:

  1. 它可以防止对象彼此相交(近层总是出现在更远的层之上——它们永远不会相交)。有时这是你希望通过 fps 实现的东西,枪总是在一切之上
  2. 您的深度缓冲区将无法用于 postfx(景深等)或延迟渲染之类的东西。
于 2010-02-12T13:11:56.420 回答