Привел от рисовку объектов при Direct3D10 рендере в порядок. Теперь они не исчезают при большом расстоянии от камеры.
В движке есть понятие Lod для шейдеров. С каким-то шагом можно задавать более сложные шейдеры для объектов. Это дает прирост производительность на старом железе(а может и на новом). К примеру возьмём дерево, которое анимируется на ветру вершинным шейдером, в шейдере есть тригонометрическая функция для нее генерируется достаточно много инструкций, очевидно дерево можно не анимировать с очень большого расстояния, в этом случае включится простой шейдер, просто трансформирующий вершину. Другой пример - нет смысла делать эффект бампа и освещения на большом расстоняии - можно ограничится диффузионным освещением или вообще без него. Конечно переключение возможно будет заметно. Аналогичная ситуация с анимацией травы. Можно сделать лоды для скелетной анимации. Но там более сложные параметры.
В случае OpenGL/Direct3D9, если не будет найден подходящий лод, то будет выставлены NULL шейдеры, т.к. для них есть фиксированный конвейер то можно вызвать IDirect3DDevice9::SetTransform(world) и glLoadMatrixf(worldViewMatrix). Для Direct3D10 в этом случае не будет ничего рисоваться. Я решил эту проблему таким образом. Для каждого формата вершин создал список шейдеров по умолчанию. В случае выставления NULL шейдера, будет браться шейдер по умолчанию, если есть вершинный буфер.
Это простое и удобное решение. Не нужно дополнительных шейдеров, тем более шейдера по умолчанию простые и короткие, поэтому их код хранится прямо в реализации класса рендера движка. Для шейдеров с альфа тестом, есть дополнительный список шейдеров по умолчанию для каждого формата, само собой с параметром - текущий AlphaRef, тут имеется ввиду значение, передаваемое в IDirect3DDevice9::SetRenderState(D3DRS_ALPHAREF, AlphaRef) в Direct3D9 и в glAlphaFunc(func, AlphaRef) в OpenGL. В Direct3D10 убран альфа тест из FFP, поэтому нужен такой параметр по которому делается discard.
Таким образом объекты перестали исчезать.
четверг, 13 ноября 2008 г.
понедельник, 10 ноября 2008 г.
Добавлен встроенный профайл
Добавил в движок встроенный профайл. По очень простой схеме,
некий класс содержащий данные о текущей строке имени файла и имени функции. Этот класс имеет конструктор с такими параметрами. С помощью макроса
#define PROFILE Profile::ProfileData data(__FILE__, __LINE__, __FUNCTION__);
можно в начале любой функции добавлять отсчёт времени. В конструкторе запоминается стартовое время работы. В деструкторе формируется строка в виде "File, line, function, time"
и рассчитывается время работы функции, данные добавляются с список. Все банально и просто. Нужно ещё решить как-то проблему мигания значение цифр, что происходит из-за разброса значений времени.
некий класс содержащий данные о текущей строке имени файла и имени функции. Этот класс имеет конструктор с такими параметрами. С помощью макроса
#define PROFILE Profile::ProfileData data(__FILE__, __LINE__, __FUNCTION__);
можно в начале любой функции добавлять отсчёт времени. В конструкторе запоминается стартовое время работы. В деструкторе формируется строка в виде "File, line, function, time"
и рассчитывается время работы функции, данные добавляются с список. Все банально и просто. Нужно ещё решить как-то проблему мигания значение цифр, что происходит из-за разброса значений времени.
четверг, 6 ноября 2008 г.
Объединение одинаковых пересекающихся объектов на сцене.
При сильно загруженной сцене бывает очень много вызовов от рисовок геометрии, всем известными под названием DIP (IDirect3DDevice9::DrawIndexedPrimitive для Direct3D9, glDrawElements для OpenGL и ID3D10Device::DrawIndexed для Direct3D10). Большое количество таких вызовов может нанести серьезный удар по быстродействию рендера, особенно это более актуально для Direct3D 9, именно в в момент вызова идет проверка на валидность пиксельного и вершинного шейдера, правильная линовка данных передаваемых из вершинного в пиксельный, проверка вершинных деклараций на соответствие того что использует вершинный шейдер и что находится в вершинном буфере, так-же индексы вершин и остальные параметры. В OpenGL все намного проще, после выполнения каждой функции может возникнуть ошибка. Таким образов время как-бы равномерно распределяется между всеми вызовами функция перед вызовом от рисовки.
Ну в Direct3D 10 DIP cost значительно снижен.
Так-же частые вызовы может серьёзно нагрузить CPU по вызовам функций. Обычно до 1000 DIP на кадр ещё не все так плохо.
Итак при загрузки сцены я сделал некую простейшую оптимизацию, ищем объекты с одинаковы мешами и если они пересекаются своими ограничивающими боксами, собираем их в 1 мешь с учтя матрицу трансформации. Что это дает?
1) уменьшение нагрузки на CPU при обходе Scene Graph и при сортировке объектов;
2) уменьшение DIP cost при отриcовке в Depth текстуру для теней;
3) уменьшение DIP cost при финальной от рисовке объектов;
Минусы в том что будет небольшой перерасход памяти. Но если к примеру у меня на сцене дерево ели имеет 350 полигонов и их несколько сотен, то объедение по 3-4 в 1 мешь будут значительно сокращать DIP cost. Пока тесты особых положительных результатов не дали но число DIP и число объектов в кадре значительно сокращены в грубом приближении на 30% в среднем. Повышение FPS вроде не более 10%. Буду тестировать на более слабом железе. На будущее конечно нужно подумать об использовании Instansing'а. Железо сейчас c такой функциональностью уже достаточно доступно и инстансинг есть уже в 3 API в том числе и поддержка у ATI для OpenGL.
Ну в Direct3D 10 DIP cost значительно снижен.
Так-же частые вызовы может серьёзно нагрузить CPU по вызовам функций. Обычно до 1000 DIP на кадр ещё не все так плохо.
Итак при загрузки сцены я сделал некую простейшую оптимизацию, ищем объекты с одинаковы мешами и если они пересекаются своими ограничивающими боксами, собираем их в 1 мешь с учтя матрицу трансформации. Что это дает?
1) уменьшение нагрузки на CPU при обходе Scene Graph и при сортировке объектов;
2) уменьшение DIP cost при отриcовке в Depth текстуру для теней;
3) уменьшение DIP cost при финальной от рисовке объектов;
Минусы в том что будет небольшой перерасход памяти. Но если к примеру у меня на сцене дерево ели имеет 350 полигонов и их несколько сотен, то объедение по 3-4 в 1 мешь будут значительно сокращать DIP cost. Пока тесты особых положительных результатов не дали но число DIP и число объектов в кадре значительно сокращены в грубом приближении на 30% в среднем. Повышение FPS вроде не более 10%. Буду тестировать на более слабом железе. На будущее конечно нужно подумать об использовании Instansing'а. Железо сейчас c такой функциональностью уже достаточно доступно и инстансинг есть уже в 3 API в том числе и поддержка у ATI для OpenGL.
Подписаться на:
Сообщения (Atom)