Подтвердить что ты не робот

OpenGL - вопрос об использовании glDepthMask

Я сделал объект A в сцене следующим образом. Сцена также имеет много других объектов.

void Draw()
{    
    if( glIsList( displayListID ) )
    {
        glPushAttrib( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT );

        glEnable( GL_BLEND );
        glEnable( GL_DEPTH_TEST );
        //glDepthMask( GL_FALSE );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

        glEnable( GL_LINE_SMOOTH );
        glEnable( GL_POINT_SMOOTH );
        glEnable( GL_POLYGON_SMOOTH );

        glMatrixMode( GL_MODELVIEW ); 

        color.setAlpha(alpha); // set alpha transparent of this objectA
        glCallList( displayListID );

        //glDepthMask( GL_TRUE );
        glDisable( GL_BLEND );  

        glPopAttrib();
    }
}

Теперь вот проблема,

Как показано, я прокомментирую две строки //glDepthMask (GL_FALSE); //glDepthMask (GL_TRUE);

сцена позволяет объекту A и другим объектам правильно углубленно. Однако, модификация объекта А альфа больше не работает (т.е. color.setAlpha(alpha)).

Если я раскомментирую эти две строки, то альфа-модификация вернется к работе. Однако рендеринг глубины НЕ правильный. Другими словами, иногда объект A должен находиться за другими объектами, но он выглядит как объект A перед всеми объектами.

Как исправить эту проблему?

Спасибо

4b9b3361

Ответ 1

  • Поверните на маску глубины glDepthMask( GL_TRUE )
  • Нарисуйте все непрозрачные объекты в любом порядке
  • Отключите маску глубины glDepthMask( GL_FALSE )
  • Включите BLEND_MODE
  • Нарисуйте полупрозрачные объекты, отсортированные от самых дальних до ближайших

Зачем вы это делаете?

Есть два буфера, о которых вам нужно беспокоиться: буфера глубины и цветного буфера . Эти буферы действительно просто большие массивы 2d, каждая из которых имеет ширину x высоту экрана.

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

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

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

Затем вы 3) glDepthMask( GL_FALSE ) поворачиваете off буфер глубины для записи, 4) включаете смешение, 5) визуализируете полупрозрачные фигуры от дальнего до ближайшего. Кажется странным, да?

Когда вы выключаете маску глубины и визуализируете полупрозрачные фигуры, OpenGL все равно будет читать буфер глубины, чтобы определить, какие фрагменты нужно выбросить (т.е. если ваша полупрозрачная фигура находится за уже сформированной сплошной формой, тогда вы бросаете этот полупрозрачный фрагменты формы). Но он не будет писать в буфер глубины, поэтому, если полупрозрачная фигура действительно очень близка к глазу (например, как полупрозрачное ветровое стекло), эти фрагменты ветрового стекла не предотвращают другие фрагменты, которые на самом деле дальше от рисунка. Это важно, потому что, если ваше лобовое стекло прямо перед вами, и вы делаете его полупрозрачным, и, вы позволяете фрагментам ветрового стекла обновлять буфер глубины, тогда вы не увидите ничего другого в своей сцене, кроме лобового стекла, даже несмотря на то, что в нем есть фигуры, потому что OpenGL будет думать: "Эй, что лобовое стекло - единственное, что должен видеть пользователь, благодаря этим показаниям буфера глубины, поэтому я не буду беспокоиться о том, чтобы сделать что-нибудь еще дальше, чем это лобовое стекло". Отключение маски глубины - это способ "обманывать" OpenGL, "не зная", есть очень близкие, но полупрозрачные фрагменты.

Ответ 2

Одно из возможных решений: установить glDepthMask в GL_TRUE в любое время и нарисовать все ваши непрозрачные объекты сначала (в любом порядке, так же, как вы сейчас это делаете), затем нарисуйте все свои (полу) прозрачные объекты, отсортированные с обратной стороны.

В некоторых случаях, если вам не нужен порядок, в котором вы рисуете (полу) прозрачные объекты, и вы хотите, чтобы другие непрозрачные объекты "сияли", вы можете пропустить сортировку (полу- ) прозрачные объекты.

Ответ 3

Нет необходимости поворачивать буферную запись глубины, если вы сортируете свои полупрозрачные объекты задом наперед.
Я отрисовываю полупрозрачные объекты вот так:

  1. Нарисуйте все непрозрачные объекты в любом порядке.
  2. Включите смешивание.
  3. Нарисуйте полупрозрачные объекты, отсортированные сзади вперед.

Проблема отбрасывания фрагментов, упомянутых бобобо, возникает, когда у вас есть пересекающиеся многоугольники. Но в этом случае отключение буфера глубины не даст правильный результат во всех случаях. На первый взгляд это может выглядеть правильно, но если вы посмотрите внимательно, вы заметите неправильный порядок наложения:

Неправильное смешивание

Этот случай математически не имеет решения, так как один многоугольник должен быть растеризован раньше другого. Чтобы решить эту проблему, вы (или художник) должны разделить полигоны на пересечении в 3D-редакторе (например, Blender). Таким образом, вы разделяете свой пересекающийся объект на 2 или более и упорядочиваете их соответствующим образом по алгоритму сортировки. Затем просвечивающие части будут отображены в правильном порядке:

Правильное смешивание

Обратите внимание, что запись в буфер глубины включена на втором снимке экрана!

Если вы отключите буфер глубины, вы, естественно, получите тот же результат, но он вам не нужен. Действительно, такие проблемы с перекрытием легче увидеть, если запись в буфер глубины не отключена. Вот почему я предпочитаю не отключать его.