Oblivion. Alpha-блендинг, баги и методы решения.

-Вы верите в привидений?
-Нет, их не существует...
Ответил мой собеседник и медленно растворился в воздухе.

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

Content for New Div Tag Goes Here

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

К счастью конкретно для Обливиона можно отдельно настраивать параметр NiZBufferProperty и тем самым обойти этот баг. Правда не все так просто, за все надо платить. К слову для Fallout3 эту функцию убили, а несовершенство рендера так и осталось.

Итак. У нас есть доспех. Доспех может быть разным.

Content for New Div Tag Goes Here

В простом случае у брони отсутствует "внутренняя" часть, полигоны с текстурой рисуются с одной стороны, с другой - прозрачно. Чтоб избежать этого - либо делается копия модели и инвертируются нормали, или проще добавить "двухсторонность" через нод NiStencilProperty. Главный параметр в нем Draw Mode:

  1. DRAW_BOTH - делает поверхность двухсторонней, как если бы была ее копия с инвертированными нормалями. А заодно вдвое увеличивает количество полигонов в модели, было 10 000, отрисуется уже 20 000. Поэтому с этим надо быть по аккуратнее, чтоб FPS не упал до нуля.
    Content for New Div Tag Goes Here
  2. DRAW_CCW - то же самое, что при отсутствии NiStencilProperty, будет отрисовываться передняя сторона, в которую направлены нормали.
  3. DRAW_CW - будет отрисовываться только обратная сторона.

Теперь альфа-блендинг. Надо целиком скопировать бранч модели.

Content for New Div Tag Goes Here

И в этом новом бранче установить для NiStencilProperty DRAW_CCW. Для оптимизации, чтоб не 40 000 полигонов к примеру рисовать, а только 30 000 (это вместе с первым бранчем, который DRAW_BOTH). Затем оригинальному бранчу добавить NiZBufferProperty и установить ему следующие настройки (правый клик - Flags):

Content for New Div Tag Goes Here

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

Content for New Div Tag Goes Here

И вот буквально пять минут назад выяснилась интересная деталь. Этот фокус работает только в пределах одного меша, то есть в пределах одного бранча. Если накладываются 2 модели из разных nif-файлов, или 2 бранча один поверх другого даже в одном nif-файле, то пишите письма. Баги останутся на месте.

А еще печальнее что есть некоторый порог расстояния, на котором это перестает действовать даже внутри одной модели. И то что в NifScope работает нормально, может отвалится непосредственно в игре.