вторник, 28 февраля 2012 г.

пятница, 17 февраля 2012 г.

Bicubic Texture Filtering

Всю последнюю неделю я занимался программируемой фильтрацией текстур. А началось с того, что я решил из спортивного интереса не преобразовывать .pcx текстуры из Quake II в RGBA (моветон) и не пережимать их в BC (с потерей деталей, которых и так почти нет) а загружать  в видеопамять таблицу индексов и палитру и делать выборку из палитры прямо в шейдере. Всё бы хорошо, но при таком раскладе нельзя использовать стандартную фильтрацию текстур, т. к. в этом случае будут усредняться индексы палитры, а не сами цветовые значения, что является ошибкой. Возможное решение - сначала делать выборку из палитры, а потом вручную выполнять билинейную фильтрацию.

Решено - пишем собственную билинейную фильтрацию (а заодно и бикубическую). У NVIDIA есть .fx файл с реализацией бикубической фильтрации и пример с реализациями различных фильтраций на CUDA. Взяв их за основу и прочитав кое-какую информацию о бикубическом ресемплинге, я написал собственные реализации.

В кубической фильтрации используется формула Митчелла-Нетравали, сплайном можно управлять с помощью двух параметров - B и C. Наиболее правильная фильтрация - по Митчеллу, с параметрами B=1/3, C=1/3, но параметры можно подбирать и произвольно. Ступенчатость лучше всего сглаживается при параметрах B=1, С=0, ценой "замыливания" изображения. NVIDIA использует иную формулу, которая идентична B=0, C=3/4 при A=-3/4 (см. GPU Gems).


Некоторые заметки о ходе разработки.

Для билинейной фильтрации необходимы четыре выборки, но если использовать Gather4 из sm 5.0, можно обойтись только тремя (для RGB компонент). При сравнении аппаратной билинейной фильтрации с реализованной вручную выявилось интересная особенность: похоже, все видеокарты AMD выполняют билинейную фильтрацию со слегка сниженной точностью, т. к. на экстремально маленьких текстурах заметен бандинг. Оптимизация в принципе оправдана, т. к. на больших по размеру текстурах сниженная точность незаметна. На NVIDIA отличий между аппаратной и программной реализациями нет.

При отладке бикубической фильтрации выявились странные различия в семплировании текстур с точечной выборкой между всеми видеокартами и Reference Rasterizer. Они проявлялись в виде паразитных линий, идущих параллельно границам текселей текстуры. Первоначально отлаженный на GTX 560 шейдер работал неправильно на HD 4330, HD 48xx и HD 68xx и refrast-e. Чтобы исправить работу под старшими моделями AMD и refrast-ом, экспериментальным путём было установлено, что из текстурных координат нужно вычесть смещение в 1/512, а для серии HD 4xxx - смещение в 1/128. Само по себе это странно, и сами числа наводят на мысли - это первый случай, когда я наткнулся на такие различия. С этим надо что-то сделать. Попытка отладки шейдера в PIX-е показала, что PIX показывает финальный output пиксельного шейдера, отличный от того, что записан в render target. Приехали.

Текущая реализация бикубической фильтрации использует 16 выборок на пиксель. В CUDA-примере от NVIDIA показано, что можно уложиться в четыре выборки, но пока неясно, насколько это "честно". Есть куда копать.

И наконец, почему бикубическая фильтрация до сих пор не реализована аппаратно? (Ok, похоже, что реализована, но D3D11 доступ к ней не предоставляет). Ответ прост: она требует значительно больше вычислительных ресурсов, при этом не даёт заметного преимущества в качестве при использовании текстур большого размера. Т. к. все современные видеокарты обладают значительным количеством локальной видеопамяти, большие текстуры используются повсеместно. Впрочем, для RAGE Кармак обещал бикубическую фильтрацию (там некоторые текстуры неоправданно пожаты).

Ссылки на примеры с исходным кодом на Google Code:

cubic-plot.zip
bicubic.zip

Update Feb 25, 2012

Переписал шейдеры таким образом, чтобы семплирование текстуры осуществлялось через метод Texture.Load() вместо point-семплирования. В этом случае GPU работает чётко с целочисленными адресами, что, как и ожидалось, привело к отсутствию ошибок и идентичному результату на всех видеокартах.

bicubic-2.0.zip

Google Code

Заметил что в сабже начали использовать Bitstream Vera Sans Mono при браузинге кода. Единственный нормальный шрифт для программирования.

среда, 15 февраля 2012 г.

HAL vs Reference Rasterizer

Я столкнулся с трудным багом - реализация семплирования текстуры с nearest фильтром в видеокартах GeForce GTX 5xx отличается от такового в Microsoft Reference Rasterizer. А все современные Radeon-ы, на которых я запускал тест, показывают картинку, идентичную RefRast-y.

И самое интересное - эти отличия в GeForce приводят к визуально правильному результату, а во всех остальных случаях - проявляются артефакты. Даже отладчик шейдеров в PIX бажит :(

четверг, 9 февраля 2012 г.

Books

Купил пару новых книг:


Думаю, в описании они не нуждаются.

воскресенье, 5 февраля 2012 г.

Visual Studio Vista

10 и 11 студии ужасны. Точка.