суббота, 5 ноября 2011 г.

Материалы. Часть вторая, путь проб и ошибок.

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

Если посмотреть настройки материалов в том же 3ds Max, то мы увидим более внушительный список как карт материалов так и их настроек. В частности я не рассмотрел такие эффекты как преломление или внутреннее рассеивание света, не рассмотрел так же возможность отражения в зеркальных поверхностях, не рассмотрел эффекты рельефных поверхностей и прочее. Причина по которой я это пропустил - все это реализуется с использованием шейдеров и поддержка того или иного эффекта уже зависит не столько от настроек материала, сколько от реализации шейдеров и системы эффектов. Об этом мы поговорим позже, сейчас же сделаем небольшой экскурс в историю VBOMesh и GLScene.


В предыдущих статьях я уже упоминал о первой совместной работе с материалами сцены и чем это закончилось (возникновение OGLStateEmul), уже тогда стало понятно что продуктивной совместной работы у нас со сценой не выйдет, и дальнейший опыт это только подтвердил. Но обо всем по-порядку, для начала давайте рассмотрим материалы сцены (TGLLibMaterial) и посмотрим удовлетворяет ли он нашим запросам:
1. Свойства материала - да, свойства материала присутствуют, причем есть разделение на свойства для лицевой грани и задней.
2. Текстура - да, текстура присутствует, есть возможность добавить вторичную текстурную карту.
3. Взаимодействие текстуры с материалом - да, есть такие настройки.
4. Взаимодействие материала с вершинными атрибутами - отсутствует.
5. Блендинг - присутствует, но в ограниченном виде (объясню позже).
6. Работа с буфером глубины - частично (объясню позже).

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

Чем же меня это не устроило? Как говорится "Дьявол кроется в деталях", вот и давайте разберем эти детали. Начнем с очевидного - сцена не предоставляет возможности указания способа взаимодействия вершинных атрибутов с материалом, ограничившись простой логикой: включен материал - не работает атрибут "цвет", выключен материал - работает атрибут "цвет". Обычно этого достаточно, так как в современной графике цвет как вершинный атрибут используется очень редко по причине низкой детализации, не говоря уже о замене им таких атрибутов как "зеркальный цвет". Но, тем не менее, есть целый ряд задач (к примеру CAD, моделирование физических процессов) где использование цвета как вершинного атрибута предпочтительнее, так как получение текстурной развертки может оказаться проблемой. Мелкий минус, исправляется буквально в две строчки кода, но это уже требует модификации нескольких модулей и требует согласования с разработчиками сцены.

Идем дальше, что значит блендинг реализован частично? Дело в том, что OpenGL предоставляет 196 вариантов настройки смешивания, не считая альфатеста и возможностей предоставляемых расширением ARB_Imaging. Что же нам предоставляет материал сцены? Он предоставляет всего 6 предустановленных вариантов смешивания. Нельзя сказать что пользователи ежедневно используют все сотни вариантов настроек, эти 6 вариантов выбраны не на пустом месте, и являются наиболее часто используемыми, но, бывают случаи... Стоит заметить что впоследствии в материалах сцены все же появилась возможность вручную задавать любую из комбинаций настроек смешивания и альфатеста, но это уже было после.

Теперь поговорим о чем-то более глубоком, к примеру о буфере глубины. В момент разработки своей системы материалов у материалов GLScene вообще не было возможности как-либо поменять настройки записи/теста глубины, только применив к материалу пользовательский шейдер и обработав событие "onApply", вручную, через команды ОГЛ, задав нужные настройки теста/записи буфера глубины и отменив их после "onUnApply". Задача я бы сказал не тривиальная. При этом прямая установка таких свойств присутствовала лишь у спрайтов. Правильно, "присутствовала" в прошедшем времени. Что же случилось - эта проблема активно обсуждалась на форуме, так как периодически возникали такие ситуации, где нужно было контролировать режим записи, к примеру отображение элементов GUI, которые должны были рисоваться поверх всей сцены, или при отображении "рук" при виде от первого лица, или вывод фоновой картинки и т.д. Обсуждений было много и длились они долго, в конце-концов были внесены доработки, которые добавили еще больших проблем. Помните о спрайтах и прошедшем времени? Вот именно, теперь свойства записи/теста глубины пропали у всех объектов сцены и появились у материалов. Казалось бы все прекрасно, теперь все работает как надо, но это привело к новой проблеме - что если нам нужно установить эти свойства для фриформы, состоящей из нескольких сотней объектов, у каждого из которых свой материал(а то и несколько)? Правильно, теперь нам предлагают вручную найти все материалы этой фриформы, и установить у них интересующие нас свойства теста глубины. Задача еще более сложная чем написание своего пользовательского шейдера... Еще больше проблему может усложнить использование одного материала на нескольких объектах (об этой ситуации поговорим позже), в этом случае изменения в материале одного объекта окажут влияние на все объекты сцены, к которым применяется этот материал, что, согласитесь, не совсем хорошо. Так же стоит отметить что аналогичная ситуация наблюдается и со смешиванием, тоесть если вы захотите сделать кузов автомобиля полупрозрачным, чтоб посмотреть его внутренности, то вам придется сделать полупрозрачными все материалы кузова, что автоматически сделает полупрозрачными все аналогичные материалы на сцене.


Идем дальше, текстуры - это отдельная песня. Нет, сами текстуры в сцене сделаны неплохо, уже в то время можно было использовать множество текстурных форматов и поддерживалось множество форматов файлов текстур. В последующем это все только улучшалось, исправлялись ошибки и вводилась поддержка новых форматов текстур/файлов. Что же тут могло меня не устроить? Проблема в том, что текстура жестко связана с конкретным материалом, и если вы заходите одну и ту же текстуру, но с розовым и желтым оттенком, то вам придется создать два материала и дважды загрузить текстуру как в оперативную так и в видеопамять и в дальнейшем вы так и будете работать с двумя копиями этой текстуры. Если вы загружаете целую сцену, то возможны ситуации когда одна и та же текстура встречается десятки раз в разных местах и с разными материалами (иногда - с разными картами смешивания). В результате вы получается ошибку нехватки памяти на модельке в пару мегабайт. Это является одним из самых катастрофических мест в системе материалов сцены, на фоне него проблемы с блендингом или тестом глубины кажутся детским лепетом. Эта проблема существует в сцене и по сей день, что делает работу с материалами сцены попросту неприемлемой.

Учитывая все вышеназванное, было очевидным что нужно разрабатывать свою систему материалов, тем более сложного там ничего нет, или мне так казалось на тот момент...

Напомню, все это происходило осенью далекого 2008 года, помните что еще произошло осенью того года? Правильно, вышла первая спецификация OpenGL 3.0, перевернувшая все представление о структуре рендера и материалах в том числе, поставив во главу угла "Его Величество Шейдер". Начались скитания - использовать старую систему материалов или сделать все по-модному, через шейдера, чтоб в будущем было легко перевести весь рендер на новый API. К сожалению я поддался на соблазн перевода всего на шейдерные материалы, в результате чего было разработано множество вариантов шейдерынх материалов и библиотек, были разработаны автогенераторы шейдеров, были разработан механизм скриптовых движков и многое другое. На все про все я потратил около года. Нельзя сказать что это время прошло зря, за это время была разработана своя библиотека шейдеров, было продумано множество концепций будущего движка, было сделано множество наработок шейдеров на разные случаи жизни, откуда я по сей день таскаю куски. Но о шейдерах мы поговорим в следующий раз, сейчас нас волнует система материалов.

Первой моей ошибкой было оставить поддержку сценовских материалов. Причин тому было несколько:
  • модуль разрабатывался как надстройка над сценой, как следствие - он должен был работать с уже имеющимися ресурсами;
  • удобный редактор материалов сцены, что делал процесс работы с материалами проще;
  • для загрузки геометрии использовались сценовский GLFreeForm совместно с загрузчиками GLFileObj/GLFile3ds, которые были завязаны на системе материалов сцены.
Таким образом, оставив поддержку сценовских материалов, я решил целый ряд возникавших проблем и мог сосредоточиться на других задачах (ведь сцена как-то проработала 10 лет с существующей системой материалов). Проблемы начались потом, когда я начал стыковать новую, свою, систему материалов и текстур со сценовской. Код применения материалов стал монструозного вида, так как приходилось предусмотреть применение сценовского материала, заданно явно, заданного по имени в библиотеке, имеющего текстуру или не имеющего, с поддержкой блендинга или без, с заменой моим материалом и без, с применением моей текстуры, с текстурой сцены или явно, по хэндлу текстуры. А там еще бли объекты с одним материалом (плэйн, куб и прочее) и с мультиматериалами (фриформы, актеры и прочее), там так же приходилось учитывать все описанные нюансы, а так же предусмотреть обход отсутствующих или ошибочных материалов и дублировать всю эту кучу кода в рендере каждого объекта VBOMesh... Но выхода не было, так как я был привязан к GLVectorFileObject...

Тем не менее, поддержка сценовских материалов хоть и доставила хлопот, но позволила получить работоспособный модуль и сосредоточиться на других задачах, в частности на разработке/доработке своих модулей материалов и текстур а так же на написание своих загрузчиков векторных форматов. Но об этом в следующей части.

Комментариев нет:

Отправить комментарий