Вчера наваял тестовую реализацию поиска силуэтов в geometry shader (реализация-то у меня и раньше была, но все коды остались далеко дома, пришлось всё делать заново).
Цифры такие:
Primitive_______Faces_____FPS
Sphere__________960______1220
Sphere__________3868_____1013
ChamferBox______4784_____962
Sphere__________16128____548
Т. е. даже для высокополигональных моделей (ну не 100 тысяч полигонов, конечно) low-end HW показывает хорошую скорость. К слову, шейдинг той же сферы вызывает намного более сильное падение числа кадров, нежели увеличение нагрузки на GS.
Думается, hi-end HW сможет без труда обрабатывать в GS до полумиллиона треугольников.
среда, 30 июня 2010 г.
суббота, 26 июня 2010 г.
Penumbra Construction
Взял свои старые (2008 г) разработки в конструировании пенумбры в GS, переписал и соптимизировал код.
Видео, как это работает для прямоугольного источника света:
Кстати, я как-то возился со своей демкой WALLE (надо выложить архив с ней), и выяснилось, что боттлнеком в ней был вовсе не pixel shader, а geometry shader. Было это на видеокарте Radeon HD 2400, в которой эта стадия тормозила безбожно, так же как и на первых G8x от NVidia. Но из тестов на своей HD 5770 я сделал вывод, что geometry shader стал работать ощутимо быстрее, чем раньше, и теперь его можно относительно безболезненно использовать даже в случае сложной геометрии.
Видео, как это работает для прямоугольного источника света:
Кстати, я как-то возился со своей демкой WALLE (надо выложить архив с ней), и выяснилось, что боттлнеком в ней был вовсе не pixel shader, а geometry shader. Было это на видеокарте Radeon HD 2400, в которой эта стадия тормозила безбожно, так же как и на первых G8x от NVidia. Но из тестов на своей HD 5770 я сделал вывод, что geometry shader стал работать ощутимо быстрее, чем раньше, и теперь его можно относительно безболезненно использовать даже в случае сложной геометрии.
четверг, 24 июня 2010 г.
понедельник, 21 июня 2010 г.
Just New Lookups
Продолжаю копать тему таблиц для теней.
Выяснилось, что авторы используют coverage с диапазоном значений [0..0.5] (заглянул в пейпр), тогда как я в позапрошлом посте показал таблицы с диапазоном [-0.5..0.5] (ноль в этом диапазоне представляется серым цветом). Отличие состоит в том, что оригинальные penumbra wedges рисуются двумя полуклиньями, и для каждого делается либо аддитивный, либо субтрактивный блендинг (деление на два полуклина было необходимо из-за нестыковки между пенумброй и границой чёткой тени, разделение на две части решало проблему). Deferred shaded подход к закраске требует рассчитывать положительное или отрицательное значение coverage (-0.5..0.5), ориентируясь по знаку z компоненты векторного произведения в шейдере.
С этим расчётом таблицы и строились. Но уже в процессе подготовки я понял, что с выборкой в шейдере предрассчитанного значения я тоже сталкиваюсь с проблемой нестыковки на границе чётких теней, из-за ограниченного разрешения субтекстур. Для обхода проблемы я планировал разбить шейдинг пенумбры на два этапа: основную часть закрашивать шейдером с lookup таблицы, а остальные пиксели, близкие к чётким границам - без таблицы. Теперь же мне в голову пришла такая мысль: подготовить таблицу с диапазоном значений [0..0.5], а знак продолжать вычислять в шейдере (две-три инструкции). Т. е. вот есть у нас пиксель на границе чёткой тени. Coverage тут может быть либо 0.5, либо -0.5, как фишка ляжет. Сэмплируем значения, близкие к 0.5 из таблицы, а знак определяем вычислением. Это уберёт большинство проблем, а остальные можно залечить в screen-space.
Пока как-то так. Конечно, окончательные выводы можно будет сделать только после тестов.
Вот как выглядят новые таблицы:
Выглядят они более "правильно", из-за симметрии что-ли. Размер субтекстуры - 32х32, т. е. получается таблица размерностью 1024x1024, при формате R8_UNORM займёт 1 MB видеопамяти (таблицу таких размеров использовали авторы оригинального алгоритма). Возможно, для минимизации проблем с точностью придётся использовать субтекстуру 64x64, а это уже 16 MB видеопамяти.
Выяснилось, что авторы используют coverage с диапазоном значений [0..0.5] (заглянул в пейпр), тогда как я в позапрошлом посте показал таблицы с диапазоном [-0.5..0.5] (ноль в этом диапазоне представляется серым цветом). Отличие состоит в том, что оригинальные penumbra wedges рисуются двумя полуклиньями, и для каждого делается либо аддитивный, либо субтрактивный блендинг (деление на два полуклина было необходимо из-за нестыковки между пенумброй и границой чёткой тени, разделение на две части решало проблему). Deferred shaded подход к закраске требует рассчитывать положительное или отрицательное значение coverage (-0.5..0.5), ориентируясь по знаку z компоненты векторного произведения в шейдере.
С этим расчётом таблицы и строились. Но уже в процессе подготовки я понял, что с выборкой в шейдере предрассчитанного значения я тоже сталкиваюсь с проблемой нестыковки на границе чётких теней, из-за ограниченного разрешения субтекстур. Для обхода проблемы я планировал разбить шейдинг пенумбры на два этапа: основную часть закрашивать шейдером с lookup таблицы, а остальные пиксели, близкие к чётким границам - без таблицы. Теперь же мне в голову пришла такая мысль: подготовить таблицу с диапазоном значений [0..0.5], а знак продолжать вычислять в шейдере (две-три инструкции). Т. е. вот есть у нас пиксель на границе чёткой тени. Coverage тут может быть либо 0.5, либо -0.5, как фишка ляжет. Сэмплируем значения, близкие к 0.5 из таблицы, а знак определяем вычислением. Это уберёт большинство проблем, а остальные можно залечить в screen-space.
Пока как-то так. Конечно, окончательные выводы можно будет сделать только после тестов.
Вот как выглядят новые таблицы:
Выглядят они более "правильно", из-за симметрии что-ли. Размер субтекстуры - 32х32, т. е. получается таблица размерностью 1024x1024, при формате R8_UNORM займёт 1 MB видеопамяти (таблицу таких размеров использовали авторы оригинального алгоритма). Возможно, для минимизации проблем с точностью придётся использовать субтекстуру 64x64, а это уже 16 MB видеопамяти.
вторник, 15 июня 2010 г.
Yet Another Order Independent Transparency Demo
Дописал новую демку, о которой писал в позапрошлом посте.
Ссылка: oit_dx
Скриншот:
Видео:
OIT 01
OIT 02
Доступны варианты для DX10 и DX11, последний показывает ускорение 3.5х (Radeon HD 5850).
Источником вдохновения стала демка из NVIDIA Direct3D SDK 10, но я не стал реализовывать преломления.
Спекуляр добавляет plastic-look к моделям, тогда как мне хотелось сделать их похожими на стеклянные. Для этого можно было бы использовать кубическую текстуру для отражений.
Возможно, что позже я доработаю визуальную составляющую демки, а также поэкспериментирую с разными моделями поглощения света.
Ссылка: oit_dx
Скриншот:
Видео:
OIT 01
OIT 02
Доступны варианты для DX10 и DX11, последний показывает ускорение 3.5х (Radeon HD 5850).
Источником вдохновения стала демка из NVIDIA Direct3D SDK 10, но я не стал реализовывать преломления.
Спекуляр добавляет plastic-look к моделям, тогда как мне хотелось сделать их похожими на стеклянные. Для этого можно было бы использовать кубическую текстуру для отражений.
Возможно, что позже я доработаю визуальную составляющую демки, а также поэкспериментирую с разными моделями поглощения света.
понедельник, 14 июня 2010 г.
4D Lookup Table
Вот уже довольно много времени прошло, как я вернулся к теме мягких теней. И хотя пространный пост о тенях будет позже, опишу, что я сделал из последнего.
Как-то по работе пришла мысль запечь одну непортируемую функцию в lookup table, но тогда ничего из этого не получилось, т. к. кол-во параметров и объём данных грозили превратить таблицу в гигабайтного монстра. Зато появилась идея реализовать lookup table для быстрого расчёта coverage источника света силуэтным ребром. Это функция от четырёх параметров - (x1,y1) и (x2,y2). Идеально подошла бы 4D-текстура или массив 3D-текстур, но железо не поддерживает ни один из этих вариантов. Выход прост - закодировать четырёхмерную таблицу в 2D-текстуре.
Вот как выглядит вариант такой 4D-таблицы для прямоугольного источника света:
Хотя набросать черновой вариант расчёта оказалось достаточно просто, выяснилось, что очень сложно добиться numerical stability для граничных случаев. И хотя мне удалось минимизировать эту проблему, она всё же кое-где даёт о себе знать:
Доработал вариант 4D-таблицы для сферического источника света. Выглядит она вот так:
Особенность расчёта этой таблицы в том, что отсутствуют проблемы с numerical stability, т. к. расчёты для диска проще. Подготовка таблицы помогла мне выявить потенциальные баги в математике, которых, как я считал, нет. У меня было два варианта расчёта coverage диска: один - точный, другой - ускоренный, с меньшим кол-вом мат. операций. Оба варианта почти всегда давали идентичный результат в test case, который я подготовил, при этом сам тест предполагал самые различные ориентации ребра. Как выяснилось, некоторые симметричные варианты расположения вершин всё же дают неправильный coverage в "быстром" варианте расчёта, поэтому он не годится. В принципе это уже не имеет значения, т. к. таблица как раз и призвана заменить эти расчёты выборкой.
Надеюсь, эти варианты таблиц можно будет использовать для первоначального ускорения алгоритма мягких теней. Что же быстрее - выборка или математические операции в шейдере? Дело в том, что мат. операции сами опираются на дополнительные выборки из кубической текстуры (2 выборки) и 2D-текcтуры (одна выборка), т. ч. в любом случае получается экономия.
Как-то по работе пришла мысль запечь одну непортируемую функцию в lookup table, но тогда ничего из этого не получилось, т. к. кол-во параметров и объём данных грозили превратить таблицу в гигабайтного монстра. Зато появилась идея реализовать lookup table для быстрого расчёта coverage источника света силуэтным ребром. Это функция от четырёх параметров - (x1,y1) и (x2,y2). Идеально подошла бы 4D-текстура или массив 3D-текстур, но железо не поддерживает ни один из этих вариантов. Выход прост - закодировать четырёхмерную таблицу в 2D-текстуре.
Вот как выглядит вариант такой 4D-таблицы для прямоугольного источника света:
Хотя набросать черновой вариант расчёта оказалось достаточно просто, выяснилось, что очень сложно добиться numerical stability для граничных случаев. И хотя мне удалось минимизировать эту проблему, она всё же кое-где даёт о себе знать:
Доработал вариант 4D-таблицы для сферического источника света. Выглядит она вот так:
Особенность расчёта этой таблицы в том, что отсутствуют проблемы с numerical stability, т. к. расчёты для диска проще. Подготовка таблицы помогла мне выявить потенциальные баги в математике, которых, как я считал, нет. У меня было два варианта расчёта coverage диска: один - точный, другой - ускоренный, с меньшим кол-вом мат. операций. Оба варианта почти всегда давали идентичный результат в test case, который я подготовил, при этом сам тест предполагал самые различные ориентации ребра. Как выяснилось, некоторые симметричные варианты расположения вершин всё же дают неправильный coverage в "быстром" варианте расчёта, поэтому он не годится. В принципе это уже не имеет значения, т. к. таблица как раз и призвана заменить эти расчёты выборкой.
Надеюсь, эти варианты таблиц можно будет использовать для первоначального ускорения алгоритма мягких теней. Что же быстрее - выборка или математические операции в шейдере? Дело в том, что мат. операции сами опираются на дополнительные выборки из кубической текстуры (2 выборки) и 2D-текcтуры (одна выборка), т. ч. в любом случае получается экономия.
четверг, 10 июня 2010 г.
Mesh Thickness
Экспериментирую с OIT и A-буфером. Вчера реализовал подсчёт толщины замкнутого меша с точки зрения камеры и затухание по экспоненте (аналогично демке в NV SDK 10).
Т. к. под reference rasterizer сложные модели уже не отладить, пока использую stencil routed K-buffer. Красным цветом помечены области, где overdraw > 4 (максимальный MSAA, который поддерживает HD 4330). Нужно сделать вывод в два K-буфера, чтобы аккумулировать хотя бы 8 слоёв и иметь картинку без "пробелов". Финальный вариант демки будет работать через A-buffer.
Т. к. под reference rasterizer сложные модели уже не отладить, пока использую stencil routed K-buffer. Красным цветом помечены области, где overdraw > 4 (максимальный MSAA, который поддерживает HD 4330). Нужно сделать вывод в два K-буфера, чтобы аккумулировать хотя бы 8 слоёв и иметь картинку без "пробелов". Финальный вариант демки будет работать через A-buffer.
вторник, 8 июня 2010 г.
printf() в шейдере
Вышел новый DirectX SDK (June 2010). В шейдерах появились новые функции:
printf, errorf, abort.
Приехали :)
printf, errorf, abort.
Приехали :)
D3D10: отличия в реализациях run-time
Вчера наткнулся на любопытный баг, связанный с некорректной реализацией ранних версий рантайма Direct3D 10.0. Я использовал код двухлетней давности, в котором создавал multisampled depth/stencil буфер с флагами D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE. Последний флаг был необязателен, т. к. ресурс служил только как render target. Тогда код работал замечательно, но теперь при попытке реюзать его под feature level 10.0 рантайм выдал в debug output такое сообщение:
Это значит, что старые Direct3D 10 программы могут накрыться с новым ран-таймом (Windows 7). Реально это, конечно, ошибка, т. к. multisampled D/S не может читаться в feature level 10.0 (только multisampled RT и non-multisampled D/S). С другой стороны, D3D10_BIND_SHADER_RESOURCE почти всегда используется совместно с D3D10_BIND_RENDER_TARGET, поэтому неудивительно, что он случайно остался в флагах после копи-паста.
И в Microsoft для D/S этот флаг прозевали.
И старый код теперь некорректный.
P.S. В feature level 10.1 можно читать из multisampled D/S.
D3D10: ERROR: ID3D10Device::CreateTexture2D: If the device interface is D3D10.0 or the driver/hardware are D3D10.0 (regardless of API version), a Texture2D with sample count > 1 cannot have both D3D10_BIND_DEPTH_STENCIL and D3D10_BIND_SHADER_RESOURCE. This call may appear to incorrectly return success on older/current D3D10 runtimes due to missing validation, despite this debug layer message. [ STATE_CREATION ERROR #99: CREATETEXTURE2D_INVALIDBINDFLAGS ]
Это значит, что старые Direct3D 10 программы могут накрыться с новым ран-таймом (Windows 7). Реально это, конечно, ошибка, т. к. multisampled D/S не может читаться в feature level 10.0 (только multisampled RT и non-multisampled D/S). С другой стороны, D3D10_BIND_SHADER_RESOURCE почти всегда используется совместно с D3D10_BIND_RENDER_TARGET, поэтому неудивительно, что он случайно остался в флагах после копи-паста.
И в Microsoft для D/S этот флаг прозевали.
И старый код теперь некорректный.
P.S. В feature level 10.1 можно читать из multisampled D/S.
Подписаться на:
Сообщения (Atom)