Разработка системы шейдерных материалов
DESCRIPTION
Разработка системы шейдерных материалов. Андрей Аксенов shodan NOSPAM @ NOSPAM shodan.ru КРИ ’2005. Обозначения. шейдер конкретная GPU микропрограмма , загружаемая в память GPU константа передающаяся в шейдер параметр любое свойство материала ( в основном доступное дизайнеру). - PowerPoint PPT PresentationTRANSCRIPT
Разработка системы шейдерных Разработка системы шейдерных материаловматериалов
Андрей Аксенов
shodan [email protected]
КРИ’2005
ОбозначенияОбозначения
шейдер– конкретная GPU микропрограмма,
загружаемая в память GPU константа
– передающаяся в шейдер параметр
– любое свойство материала (в основном доступное дизайнеру)
ОбозначенияОбозначения (2) (2)
текстура– один из видов параметра
прешейдер– формула вычисления константы из
параметров материала и сцены пин
– переменная времени компиляции, влияющая на выбор конкретного шейдера
ОбозначенияОбозначения (3) (3)
привязка (биндинг)– процесс назнчения текстур в
текстурные стейджи, заливки шейдерных констант, итп
материал– набор шейдеров и параметров (общая
статическая таблица для всех объектов класса и агрегированные значения параметров в объектах)
2002-2002-й годй год……
Это была тестовая карта!
Начальный проект шейдингаНачальный проект шейдинга
проходы
1. shadow map
2. diffuse / specular (основной)
3. EM / EMBM (опционально) пины (разбиения шейдеров)
1. static / skinned ( 1/2/3/4 кости )
2. NV / ATI ( наличие SM hack )
3. EM / EMBM
ЭволюцияЭволюция шейдингашейдинга
дополнительные пины– тип тумана ( range / height )– коррекция блендинга для тумана– итд итп
небольшой комбинаторный взрыв– ~150 шейдеров– 3..5 факторов для выбора шейдера– 8 разных мест для ручной
регистрации каждого шейдера
ЭволюцияЭволюция шейдингашейдинга (2) (2)
единый общий класс материала– 5 текстур– ~15 параметров
сложности управления– неочевидные факторы и сложная
функция привязки материала (пример: (pBump!=NULL) )
– трудоемкость дальнейшего разбиения шейдеров
Расширение единого классаРасширение единого класса??
означает добавление параметров– как минимум 8 семантик текстур– как минимум 20-30 параметров– одновременно не используются
означает еще большую сложность– функция привязки более 1000 строк– еще больше заполняемых вручную
таблиц выбора шейдеров…
Нужна система материаловНужна система материалов!!
система материалов?
– некоторый общий (для нескольких проектов) код, который максимально автоматизирует создание новых видов шейдерных материалов и их внедрение в проекты
Требования к системеТребования к системе
простота создания новых материалов– как минимум, регистрация нового
материала не более, чем в 1-2 местах– как максимум, загрузка на лету
простота создания новых пинов– иначе добавлять к существующим
материалам функциональность слишком трудоемко
Требования к системеТребования к системе (2) (2)
простота создания новых shading path и проходов внутри shading path– shading path отличается от пина тем,
что влияет на число проходов и привязку каждого прохода
простота создания прешейдеров– в хардкоде “прешейдер” задавался в
функции привязки, отдельно от материала - неудобно
Требования к системеТребования к системе (3) (3)
менеджмент упакованных и композитных текстур– для облегчения работы дизайнеров и
минимизации человеческих ошибок– автоматическая упаковка в DXT– автоматическое смешивание каналов
исходных текстур (не используемых напрямую) в одну, используемую шейдером ( bump.rgb + gloss.a )
Почему не Почему не D3DXEffect?D3DXEffect?
проблема черного ящика– а точнее, имеющегося качества и
скорости поддержки… проблемы кодогенерации FXC
– недостаточно хорошая оптимизация– недостаточно гибкая привязка
констант– полное отсутствие контроля за
прешейдерами
Почему не Почему не D3DXEffect? (2)D3DXEffect? (2)
проблема сортировки по текстурам и шейдерам– как сделать эффективно?
проблема сопряжения со специфичными типами данных– контроллеры анимации– композитные текстуры– решаемо посредством оберток, но нет
гарантий эффективности
Архитектура системыАрхитектура системы
class FXMaterial_c– базовый абстрактный интерфейс– реализация общей функциональности
конкретные реализации материалов– class FXMaterial_Diffuse_c
: public FXMaterial_c– агрегирует конкретные параметры– реализует функции привязки
Архитектура системыАрхитектура системы (2) (2)
препроцессор спецификаций FXPP
(FX Preprocessor)– генерирует весь C++ код реализации
материала ( FXMaterial_Diffuse_c )– в том числе, заранее компилирует все
возможные уникальные HW шейдера, необходимые данному виду материала
– использует спецификацию материала
Блок спецификацииБлок спецификации
material{
// пиныcompilevar USE_BONES;compilevar USE_SHADOW;compilevar USE_SHADOW4SAMPLE;compilevar USE_FOG_TYPE;compilevar USE_OMNIGROUPS;
// параметры материалаtexmap texDiffuse { uiname="Diffuse map"; }uivar color3 cLuminosity;uivar color3 cDiffuse;uivar float fShadowTransp;uivar texgen2 tgDiffuse;
// ...
Блок спецификацииБлок спецификации (2) (2)
path default{
pass 0{
stage 0 = scene.ShadowMap;stage 3 = texDiffuse;float4 vs.g_cAmbiLumi = mat.cLuminosity +
mat.cDiffuse*scene.cSunAmbient;float4 vs.g_cTotalDiffuse =
mat.cDiffuse*scene.cSunDiffuse;float4 vs.g_cMatDiffuse = mat.cDiffuse;float4 vs.g_tgDiffuse0 = mat.tgDiffuse.GetXform(0);float4 vs.g_tgDiffuse1 = mat.tgDiffuse.GetXform(1);float4 ps.g_cShadowTransp = { 0, 0,
1-scene.fShadowTransp*mat.fShadowTransp/2.0f,scene.fShadowTransp*mat.fShadowTransp/2.0f };
float4 ps.g_cAlpha = { 0, 0, 0, frag.iAlpha/255.0f };}
}
Задание шейдеровЗадание шейдеров
по имени (жесткая схема именования) либо ассемблер, либо HLSL общий код через # include возможность копирования реализации
// HLSLLitVertex_t vs_default_pass0 ( SkinVertex_t IN ) { ... }
// asmVertexShader vs_default_pass0 = asm { ... }
// implementation copyVertexShader vs_r9700_pass0 = vs_default_pass0;
Препроцессинг Препроцессинг FXFX
разбор спецификации компиляция всех возможных шейдеров
– варьируем значения пинов– привязываем константы:
• uniform float4 g_cDiffuse : register ( c13 );• # define VS_g_cDiffuse c13
отсев дублирующихся шейдеров генерирование C++ кода материалов генерирование общего C++ кода
C++C++ код материала код материала
бинарные данные шейдеров таблица шейдеров, ее инициализация дескриптор параметров функция привязки шейдеров
– выборка по таблице в зависимости от shading path, номера прохода и значений пинов
функции привязки констант– в зависимости от shading path, прохода, пинов– разделение на per-material / per-instance
Общий Общий C++C++ код код
списки (enum) ID материалов константы ( FX_PINS_TOTAL итп ) функция создания материала по ID декларации классов инициализация запросы к дескрипторам материалов по ID union FXInstanceFlags_u
содержащий пины в виде битовых полей
Функциональность Функциональность FXMaterial_cFXMaterial_c
общие параметры ( альфареф, флаги, … ) бинарный и текстовый сериализаторы управление текстурами, в том числе
упакованными и композитными управление значениями параметров привязка рендерстейтов поддерживающие функции
( GetFlags, operator =, и т.п. )
Дескриптор параметровДескриптор параметров
для каждого параметра заданы:
тип ( eg. COLOR ) UI имя ( eg. “Diffuse color” ) техническое имя ( eg. “cDiffuse” ) смещение в базовом классе флаг доступности дизайнеру через UI диапазон возможных значений ( для UI )
Как решены проблемыКак решены проблемы D3DX? D3DX?
проблемы поддержки нету проблемы оптимизации – обходим,
используя ассемблерные шейдеры проблемы привязки – решаем, привязывая
константы из FXPP проблему прешейдеров – решаем,
генерируя C++ код привязки констант– который в итоге компилируется в инлайновые
SSE инструкции
Как решены проблемыКак решены проблемы D3DX?(2) D3DX?(2)
cортировка – по следующему 64-битному ключу:
struct{
DWORD m_uMesh : LOG2<MAX_MESHES>::Value;DWORD m_uPins : FX_PINS_TOTAL;DWORD m_uMaterial : LOG2<FXMAT_TOTAL>::Value;DWORD m_uTexture : LOG2<MAX_TEXTURES>::Value;
};__int64 m_uValue;
порядок полей определяет приоритеты сортировки
Специальные типы параметровСпециальные типы параметров
на примере композитных текстур: введен подтип у типа параметра
FXPARAM_TEXTURE введено два новых ключевых слова
compositemap, submap в спецификацию доработана функция SetMap написаны функции обновления и
сохранения
Итого: 1-2 рабочих дня на сложный (!) тип.
Известные проблемыИзвестные проблемы
отсутствие (пока) разных типов инстанса– для разных моделей нужная разная per-
instance информация – примеры – fading, instancing
отсутствие (пока) удобных деклараций для сложных массивов констант– примеры – skinning, упаковка групп
источников света
дублирование кода между некоторыми видами материалов ( Diffuse, DiffuseEnv )
ИтогиИтоги
добавление новых (фактически, Иных) материалов – сводится к созданию FX-файла в директории с материалами– конечно, неплохо бы еще и в dependencies
прописать…
добавление новых пинов – сводится к добавлению одной строчки в FXPP– например, добавление нового типа тумана
или портирование всех шейдеров на ps_1_4
ИтогиИтоги (2) (2)
разработка окупается– на разработку ушло МНОГО времени– на добавление в хардкод и отладку одних
только автоматически добавленных в новой системы разбиений по пинам – ушло бы время сравнимого порядка
стоит ли писать свою систему?– вопрос неоднозначный!– если не устраивает хардкод (много шейдеров)– если не устраивает D3DX
Занимательная нумерологияЗанимательная нумерология
45-50 дней по трекеру, планировалось 15 11 видов материалов, 89 килобайт FX всего компилируется 2842 варианта HW
шейдеров, из них 532 уникальны компиляция длится 75 секунд генерируется 75809 строк C++, 3298 KB
– за вычетом собственно бинарных шейдеров, остается 5239 строк, или 328 KB
FXPP это 2268 строк кода, или 61 KB,и самое страшное…
Занимательная нумерологияЗанимательная нумерология (2) (2)
FXPP написан на Perl.
# store original line numbers$l = 0; $fx =~ s/^/++$l.":"/gems;
# remove /*...*/ comments$fx =~ s/\/\*.*?\*\///gms;
# remove // comments$fx =~ s/^((([^\/"\n])|("[^"]*"))*)\/\/.*$/\1/gm;
# ...
# build material types list$i = 0; print OUT "enum FXMaterial_e\n{\n", join ( ",\n", map { uc "\tFXMAT_$_ = " . $i++ } @g_fx_names ), ",\n\tFXMAT_TOTAL\n};\n\n";
MIR
FIN