Создание FPS в OpenGL - PullRequest
       49

Создание FPS в OpenGL

3 голосов
/ 11 февраля 2010

Я создаю шутер от первого лица, используя OpenGL, и пытаюсь заставить модель оружия плавать перед камерой. Я разорвал модель из Fallout 3, используя декомпилятор ресурсов (преобразованный в .obj и загруженный в).

Однако на экране это выглядит так:

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 ]

2 голосов
/ 11 февраля 2010

С точки зрения (не каламбур) OpenGL, Frustrum - это просто еще одна матрица. Вы должны иметь возможность нажать матрицу проекции, вызвать gluPerspective (или glFrustrum, если вы любите приключения), чтобы установить для znear очень маленькое значение, нарисовать пистолет, затем вытолкнуть матрицу проекции и нарисовать остальную часть сцены (остерегайтесь тем не менее, стек матриц проекции часто довольно неглубок - он может составлять всего два уровня).

Одно предостережение: я никогда не задумывался над тем, как это должно повлиять на z-бой. Это может не принести никакой пользы - это может сработать так же, как если бы вы рисовали всю сцену меньшим значением znear.

2 голосов
/ 11 февраля 2010

Вы пытались протолкнуть свое оружие дальше в сцену (то есть: от камеры)? Когда вы делаете это, полигон все еще обрезается? Если нет, то, как и предполагалось, ваша модель обрезается рядом с местом отсечения (установлено в матрице проекции). Если у вас все еще есть артефакты, проблема может быть в чем-то еще: состояния рендеринга, загрузка модели и т. Д. И т. Д.

Вы видели всю модель в какой-то программе просмотра? Может быть, именно так выглядит модель, и число поли оптимизировано, потому что вам нужно увидеть эти поля в игре

2 голосов
/ 11 февраля 2010

Проблема вызвана плоскостью отсечения.

Уменьшите значение znear, которое вы использовали для расчета матрицы проекции. Только сделайте это так низко, как это необходимо. Чем оно ниже, тем больше проблем с z-боями.

0 голосов
/ 12 февраля 2010

«Наслоение» с другой матрицей проекции может быть опасным, если вы не будете осторожны, так как значения глубины между разными слоями не находятся в одном «пространстве». То, что я называю слоем здесь, представляет собой группу объектов, отображаемых с заданной матрицей проекции. Обычно есть 2 решения для этого:

  1. Рендеринг ваших различных слоев (со всеми объектами на них), начиная с самого дальнего расстояния и очищая буфер глубины между каждым рендерингом.
  2. Разделите буфер глубины между слоями, используя glDepthRange.

Обратите внимание, что использование любого из этих методов позволит вам исправить потенциальные проблемы с объектами разных слоев, сражающихся вместе, но есть некоторые недостатки:

  1. Он не позволяет объектам пересекаться друг с другом (ближние слои всегда будут появляться поверх других слоев - они никогда не пересекутся). Иногда это то, чего вы хотите достичь в любом случае с помощью fps, когда пистолет всегда на вершине всего
  2. Ваш буфер глубины будет непригоден для таких вещей, как postfx (глубина резкости и т. Д.) Или отложенный рендеринг.
0 голосов
/ 12 февраля 2010

При рендеринге близких объектов вы должны указать другую ближнюю-дальнюю плоскость отсечения, например, оружие, удерживаемое персонажем. Это приведет к тому, что значения глубины пространства окна для фрагментов будут недопустимыми по отношению к другим элементам сцены, поэтому вам также придется изменить целевой диапазон глубины, вызвав glDepthRange. Это увеличит точность в камере рядом с объектами.

Как вы упомянули, изменение только ближней плоскости вашей общей усеченной сцены не является решением или перемещением оружия вперед / назад, поскольку они создают проблемы z-боя.

0 голосов
/ 11 февраля 2010

Почему бы просто не протолкнуть пистолет дальше в сцену и увеличить его так, чтобы он не соприкасался с ближней плоскостью?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...