Создание FPS в OpenGL:Мой пистолет прижимается к усеченному усечению

StackOverflow https://stackoverflow.com/questions/2244599

  •  20-09-2019
  •  | 
  •  

Вопрос

Я создаю шутер от первого лица, используя 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);

Есть ли способ отключить обрезку только для пистолета?Как это делают другие игры?

Заранее спасибо.

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

  1. Это предотвращает пересечение объектов друг с другом (ближайшие слои всегда будут появляться поверх последующих слоев - они никогда не пересекаются).Иногда это то, чего вы все равно хотите достичь с помощью fps, когда оружие всегда на высоте.
  2. Ваш буфер глубины будет непригоден для таких вещей, как postfx (глубина резкости и т. д.) или отложенный рендеринг.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top