понедельник, 26 октября 2009 г.

How to pack normal into just 2 bytes

Необходимость в жёсткой оптимизации по чтению из памяти привели меня к упаковке предрасчитанных данных и вершин. Хотел было написать, как мне удалось реализовать упаковку нормали в unorm2 с потерей одного бита точности для хранения z sign. Но, порыскав по гуглу, нашёл великолепный анализ методов сжатия нормалей от Aras Pranckevičius (я и не думал, что их столько, видать deferred техники здорово включают изобреталку:):

Compact Normal Storage for small G-Buffers

Все представленные алгоритмы упаковывают нормаль в unorm2 и восстанавливают потерянную информацию, используя квадратный корень. Метод простой упаковки xy с последующей реконструкцией z оказался наименее качественным (зато наиболее быстрым). Видимо из-за dot(n.xy, n.xy), который усиливает ошибку квантования (а для world нормалей придётся пожертвовать ещё одним битом точности). Любопытый обзор, вероятно лучший в Сети - для поклонников deferred shading-a будет весьма ценнен. Я же собираюсь использовать наиболее быстрый вариант, т. к. у меня нормали будут интерполироваться по треугольнику, и каждую надо распаковать... Сойдёт и удовлетворительное качество, главное - минимум чтений из памяти.

2 комментария:

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

    ОтветитьУдалить
  2. Нет, для Deferred Shading-а тебе нормаль нужно интерполировать по треугольнику, паковать и записывать в G-buffer. Если будешь интерполировать уже сжатую - ничего хорошего не получится. Поэтому тут затраты на паковку/распаковку. Если пакуешь вершину - то распаковывать надо в вершинном шейдере и передавать дальше в интерполятор.

    ОтветитьУдалить