четверг, 30 сентября 2010 г.

N8

Прочитал про новый смартфон Nokia N8, и что его мол собрались продавать в городе бывшего мэра Лужкова Маскве, одновременно как и во всём мире. Хе-хе, Apple почему-то так не делает :)

Вообще, в роли догоняющей Nokia в конце-концов может и сможет создать что-нибудь этакое, только толку (как мне кажется) от этого будет немного. Проблема в том, что бренд Nokia перестал ассоциироваться с чем-то первоклассным, или, если выразиться более точно, он стал ассоциироваться с Унылым Говном, и люди с деньгами никогда не купят имиджевый смартфон этой марки. Гламурные кисо и богатые дяди купят Apple, кто-то купит что-то с WP7, кто-то - Nexus One. А Nokia...

-Что это у тебя за новый телефон?
-Nokia N8!
-A-a, понятно. (А про себя: вечно догоняющие лузеры, УГ).

P.S. Говорят, в 2011 у модных смартфонов будет новая фича: потеря сигнала при неправильном обхвате рукой :)

вторник, 28 сентября 2010 г.

How a GPU Shader Cores Work

Весьма интересные слайды с SIGGRAPH 2010, описывающие в общих чертах, как работают современные GPU, чем они отличаются от x86 CPU, как работают ветвления и сокрытие латентности памяти внутри GPU:

From Shader Code to a Teraflop: How GPU Shader Cores Work

Приводятся основные архитектурные различия между современными Radeon HD 5870 и GeForce ПЕЧ 480. Также можно посмотреть более старую версию слайдов за 2008 год, где сравниваются ПЕЧ 280, HD 4870 и Larrabee.

Не пытайтесь прочитать всё за один присест, лучше растянуть на 2-3 дня :)

воскресенье, 19 сентября 2010 г.

Occluder Fusion Problem

Есть у алгоритма penumbra wedges один существенный недостаток, бороться с которым очень сложно и в общем случае - невозможно. Недостаток заключается в том, что алгоритм неверно определяет coverage источника света в случае, если два или более ребра несколько раз перекрывают одну и ту же область - т. н. occluder fusion. Проблема вытекает из того, что пиксельный шейдер работает отдельно с каждым ребром, которое проецируется на источник света, а не со всеми сразу, и расчёт для каждого ребра никак не учитывают влияние "соседей". Как компромисс авторы в далёком 2003 предлагали использовать т. н. probabilistic approach, при котором силуэты от двух разных кастеров рисуются в отдельные RT и потом они смешиваются по формуле
c = max(Ca, Cb) + 1/2 * min(Ca, Cb)
что в результате даёт значение между двумя экстремумами. Также есть пейпр, где сабж пытались побороть с помощью penumbra wedges blending (Vincent Forest et al., Realistic Soft Shadows by Penumbra-Wedges Blending), но техника выглядит очень заумной и нежизнеспособной в real-time и не стоит подробного рассмотрения.

Хотя single point silhouette approximation представляется мне более сложной и важной проблемой, серьёзно влияющей на визуальное качество теней, occluder fusion также не давал мне покоя и я потихоньку думал, как её можно обойти на DX 11 железе. Ясно, что проблема лежит в аналитическом методе расчёта пенумбры, из-за которого, собственно, мягкие тени и выглядят как настоящие тени, а не как их жалкое подобие. Правильное решение заключается в интегрировании площади источника света с помощью множества сэмплов на его поверхности, как делается, например, в методе depth complexity sampling. Но применённый алгоритм получается медленным и не годится для real-time.

Быстрое "решение" пришло в голову, когда я обдумывал преимущества использования coverage lookup table для упрощения пиксельного шейдера. Итак, у нас есть предрассчитанный coverage для ребра с произвольными координатами двух вершин. А что, если разбить источник света на N сэмплов, и вместо coverage предрассчитывать маску охвата, как это делают GPU при мультисэмплинге? Получается маска вида 0000101100100010, её можно сохранить в integer текстуре. В Direct3D 11 доступен формат DXGI_FORMAT_R32G32B32A32_UINT, так что можно разбить площадь и. с. на 128 сэмплов при последующей одной выборке в пиксельном шейдере.


Теперь, делая такую выборку для каждого отдельного ребра, мы может просто ORить маски охвата (SM 4.0 железо и выше умеет работать с отдельными битами) и в конце получить результирующую маску, которая и описывает правильный coverage. Теперь достаточно подсчитать количество битов, выставленных в 1 (в SM 5.0 для этого даже есть подходящий интринсик - countbits(uint4 value)) и получить отношение к общему их кол-ву. В результате мы корректно проинтегрируем скрытую (видимую) площадь источника света, представленную в промежутке [0..1], которую можно сразу записывать в coverage буфер.

И все :)

P. S. На работе в непосредственной близости от меня появилась DirectX 11 система (Windows 7 + Radeon HD 5850, так что дело скоро сдвинется с места).

четверг, 16 сентября 2010 г.

Враг у ворот

Солдаты!

Все вы - граждане и защитники нашей необъятной Родины-матери! Напоминаю вам об этом ещё раз, перед тем как наши доблестные войска пересекут линию фронта! Стоять, блять, насмерть, позади - Дефолт-сити, она же - Маськва!

среда, 15 сентября 2010 г.

Bootice

Ну, граждане пограммисты, OpenGL-тролли, задроты, и просто закоренелые девственники - соскучились по записям?

В выходные слетела у меня Windows 7 (на ноуте). Бог его знает, что там произошло, только загружаться с определённого момента она стала ну о-очень долго и зависала с пустым экраном и одиноким ездящим курсором. MSI предусмотрели восстановление изначальной Vista с hidden partition на HDD, только эта утилита отформатировала мне диск C: и стабильно падала в ребут на этапе инициализации. Т. к. привода DVD в ноуте нет, пришлось научиться устанавливать Windows 7 с флешки.

Как оказалось, если просто распаковать iso-образ дистрибутива Windows на флешку, выставить в BIOS загрузку с неё, и ребутнуть систему то получим либо сообщение "Bootmgr is missing", либо "Disk error", в зависимости от флешки. Решить проблему удалось с помощью сайта flashboot.ru, где я скачал необходимые утилиты для правильного форматирования флешки и размещения на ней дистрибутива OS. Всё заработало с первой попытки и я успешно поставил Windows 7 Ultimate (была Professional). Пиратка с торрента, конечно, но я же уже заплатил за Vista при покупке ноута! MS, думаю, хватит и этого, к тому же это для безобидного домашнего пользования :)

Жаль только, что Ultimate грузится как-то медленнее, чем Professional, а ещё раз всё переустанавливать не хочется.

О житии :)

Надоело носить всякую дрянь с рынка шмоток, поэтому решил на осень сшить себе пальто. Шью себе впервые в жизни, так что опыт этот для меня новый, интересный :) Нашёл в Киеве ателье, договорился с дизайнером, показал фотки - что и как должно выглядеть... Уже нашли для меня подходящий зелёный вельвет, из Италии. Похоже, влетит мне эта штучка в 800$ (в основном - за работу), ну да фиг с ними, деньгами, молодость ведь бывает только раз в жизни. Образец для подражания - зелёный сюртук 19 века, так сказать nec plus ultra для молодого человека того времени, подпиленный для повседневного ношения на улице в наши дни.

Быть может, вы ещё его увидите :)

вторник, 7 сентября 2010 г.

VBO state reduction

Я всё же придерживаюсь мнения, что правильный способ разгона рендера - это уменьшение state changes. Я реализовал наиболее оптимальную загрузку всех костей в bindable buffers (всё-таки DX 10 фича на Mac!), на очереди встала оптимизация VBO.

Т. к. каждая часть модели (голова, туловище, руки и т. д.) в портируемом проекте находится в отдельном буфере вершин/индексов (в терминологии движка - vertex/index stream), то приходится делать множество вызовов glBindBuffer() плюс делать setup вершинных атрибутов через glVertexAttribArrayPointer(), и я вам скажу, что количества вызовов получаются страшными |(o_0)| Поэтому вполне закономерно меня посетила такая идея: рассортировать всю геометрию по типам формата вершины и загнать все кусочки VB/IB в один большой буфер вершин. Тогда достаточно лишь один раз установить VB/IB и задать смещения для атрибутов, а дальше уже рисовать нужную геометрию - экономия state changes немалая.

К сожалению, в GlukoGL 2.0 отсутствует возможность указать base vertex location непосредственно в DIP-e, а только через смещение во всё той же злополучной glVertexAttribArrayPointer(). Если мы объединяем все VB в один, то очевидно что индексы во всех индексных буферах (кроме первого) становятся невалидными. Поэтому при сливании индексов в общий IB к ним добавлялся текущий base vertex location общего VB. Кроме того, индексы в "обрезках" IB хранились в формате USHORT (что очевидно), для общего IB они преобразовывались в UINT, т. к. адресация запросто вылезает за 2^16 вершин. Также skinned модели содержали свои LOD-ы в "обрезках", поэтому дополнительно пришлось повозиться с оффсетами по памяти и другой подобной белибердой.

Не буду описывать все проблемы, которые возникли у меня с GlukoGL на NVIDIA, пока я реализовывал "склейку". Скажу только, что схема заработала и геометрия успешно рисуется через новый codepath. State changes, такие как glBindBuffer / glVertexAttribArrayPointer / glEnableVertexAttribArray уменьшились существенно - в несколько раз.

Что до производительности - в случае небольшого кол-ва видимой геометрии есть видимый прирост fps, в случае тяжёлых сцен прирост держится "на честном слове" и частенько уходит в 0. Мы всё ещё упираемся во всякие гадкие вызовы GlukoGL, которые просаживают произодительность. Ну и как оптимизировать кучу DIP-ов при текущем data set-е - тоже неясно :(

понедельник, 6 сентября 2010 г.

Жесть оцинкованная

В последнее время я подсел на чтиво в авторстве gansspb. Чем больше читаю, тем больше хочется. Жгёт товарищ :)

Кстати, мы с ним одногодки.

пятница, 3 сентября 2010 г.

My work iMac 27

Теперь и у меня на рабочем столе появился iMac (до этого стоял MacPro + монитор Philips 23 дюйма). У новой машины процессор Core i7 (да здравствует быстрая компиляция!), но, к сожалению, видеокарта ATI предыдущего поколения - HD 4850, а я уж хотел было доставить Windows 7 через bootcamp и засесть на выходных за DirectX 11 :( Ну ничего, когда-нибудь в контору придут новые iMac-и c AMD HD 6000 и я договорюсь об обмене :)

На фотках - процесс "раздевания" и запуска этой гламурной машинки:


Глянцевый Samsung XL2370 кажется карликом перед S-IPS матрицей айМака :)

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

Поэтому и пишу здесь о этом. Спасибо, тебе, Джонатан, за дизайн!

P.S. А макось+Хcode всё равно кака :)

четверг, 2 сентября 2010 г.