аппаратный tl mafia что это
Технология T&L (Трансформация и Освещение)
Необходимое вступление
NVIDIA взбудоражила рынок PC выпуском своего GeForce 256™ GPU (Graphics Processing Unit – Графический Процессор). Появление GPU с интегрированными аппаратно геометрическими процессорами и процессорами освещения – прорыв в области 3D-графики, делающий возможным создание приложений качественно нового уровня.
Трансформация и освещение
Transform and lighting (T&L) (Трансформация и Освещение) – первые две из четырех ступеней, вычисляемых GPU в 3D-конвейере. Они характеризуются высокой интенсивностью и сложностью вычислений набора очень специфичных математических инструкций (выполняемых миллиарды раз в секунду) для того, чтобы обсчитать сцену.
Для понимания роли T&L, полезно иметь представление о полном процессе создания трехмерной графики, начинающегося непосредственно с приложения. Основные функциональные шаги изображены на Рис. 1.
Рис.1 Графический 3D Конвейер
Прикладные задачи | Приложение управляет перемещениями объектов (включая камеру) и их взаимодействиями в 3D мире. Проблемы с вычислениями реалистичной физики (объекты обладают моментом) и определениями столкновений/пересечений (мой гоночный автомобиль столкнулся со стеной или другим авто?) отображаются как перемещения объектов в сцене. | ||
Задачи Уровня Сцены (отсечение, LOD, дисплейный список) | Задачи Уровня Сцены включают в себя отсечение объектов уровня (авто №3 находится полностью позади камеры, так что нет необходимости пересылать его на следующий шаг), выбор соответствующего уровня детализации (авто №1 находится далеко, так что лучше применить низко детализированную модель) и создание списка всех объектов, попадающих в текущее поле зрения камеры. | ||
Геометрическое преобразование | Геометрический процессор конвертирует 3D данные из одной системы отсчета в другую. Система должна преобразовать данные к текущему виду перед выполнением следующего шага (освещение, триангуляция/разбивка на треугольники и рендеринг). Каждый отображаемый объект и некоторые из неотображаемых должны быть преобразованы каждый раз, когда сцена перерисовывается. | ||
Освещение | Освещение – следующий шаг в 3D конвейере, производящий к тому же значительное визуальное впечатление. Эффекты освещения служат для повышения реализма сцены и приближению отрендеренных образов еще на один шаг к нашему восприятию реального мира. | ||
Triangle Setup and Clipping – Разбиение на треугольники и Отсечение | Триангуляционный процессор (процессор треугольников) – математический процессор с плавающей точкой, получающий на входе данные о вершине и выдающий на выходе все необходимые процессору рендеринга обработанные данные. Этот модуль разбивает (sets up) и отсекает (clips) треугольник для передачи его процессору рендеринга. | ||
Рендеринг | Рендеринг – это расчет правильного цвета для каждого пикселя на экране с учетом всей информации, предоставляемой процессором треугольников. Процессор рендеринга должен учитывать цвет объекта, цвет и направление света, падающего на объект, является ли объект прозрачным и в какой степени, и что за текстуры применены к объекту. Если Рендеринг завершается в несколько этапов, то такой Рендеринг называется многопроходным. |
Роль процессора геометрических преобразований (геометрического процессора)
Рис.2 Мировое Пространство
Рис.3 Экранное Пространство
Роль Процессора Освещения
Почему пользователям нужен интегрированный в GPU геометрический процессор
Расчеты геометрии (T&L) теперь стали главным препятствием на пути к совершенной 3D графике на типичных персональных компьютерах. Графический процессор стал простаивать неоправданно долго в ожидании подготовленных геометрических данных от ЦП. Это узкое место графических процессоров заставляло разработчиков снижать геометрическую детализацию 3D персонажей и сред, ухудшая их визуальное качество для того, чтобы оставить производительность приложения в целом на приемлемом уровне. Интегрированные геометрические процессоры – наиболее оправданный, по соотношению цена/производительность, способ увеличения производительности при расчетах геометрии и предоставляет новые возможности разработчикам приложений для повышения уровня детализации их 3D миров.
Рис.4 Тесселяция Сферы
На всех фрагментах Рисунка 4 изображена одна и та же сфера, но на крайнем справа – наиболее детализированная из всех трех. Она содержит в пять раз больше полигонов по сравнению с крайней левой картинкой и в три раза больше по сравнению со средней. Это значит, что правая сфера требует в пять раз более высокой скорости геометрических преобразований по сравнению с левой сферой для того, чтобы общая производительность осталась на прежнем уровне (т.е. не снизилась). Для большинства пользователей персональных компьютеров комфортная частота кадров – от 30 до 60 Гц, поэтому они (пользователи) будут стараться подстроить «качество изображения» (параметры рендеринга, разрешение и т.п.) в настройках программы, чтобы величина fps находилась в указанных пределах.
Эта простая проблема «производительность-против-качества» становится весомой, когда начинаешь понимать, что 3D сцена включает в себя от сотен до тысяч объектов, для каждого из которых надо обсчитать геометрические преобразования и освещение с помощью только лишь ЦП. Программисты должны точно оценить уровень детализации каждой модели в сцене, чтобы точно знать, что соотношение качество/производительность осталось в допустимых пределах. Если сцена представляет собой джунгли, то необходимо включить в неё заросли кустов и деревьев, т.к. одно дерево или кустик не передадут атмосферу джунглей.
Почему пользователям необходимы интегрированные в GPU процессоры расчета освещения
Рис.5 Пример Освещенности
Image courtesy of Digital Illusion.
Без интегрированного расчета освещенности будет невозможно в реальном времени точно отображать изменения свойств освещения 3D объектов при изменении положения камеры относительно источников света – для этого необходимо рассчитывать два важных для точного моделирования физики освещения параметра. Эти два компонента – рассеянный свет и отраженный свет. Под источником рассеянного света понимается источник, излучающий свет во все стороны с одинаковой интенсивностью так, что яркость отраженного от предмета света вообще не зависит от положения камеры. Солнечный свет на игровой площадке – пример рассеянного освещения в реальной жизни. Яркость объекта в 3D сцене прежде всего определяется расчетами рассеянного освещения. Отраженный свет отличен от рассеяного, т.к. зависит от положения камеры, направления на источник света и ориентации треугольника перед рендерингом. Сверкающий блик света на экране телевизора в темном углу комнаты поможет вам яснее представить отраженное освещение. Отраженный свет зависит от отражающей способности объектов, дающей эффект отражения и блика. На Рисунке 6 показаны два примера космической станции из теста 3DWinBench с эффектами рассеянного и отраженного света.
Рисунки 6 и 7
Только рассеянный свет
Рассеянный и отраженный свет
Блики отраженного света перемещаются по объекту, если движется камера, или же сам объект относительно источника света. По этой причине они не могут быть заранее посчитаны и заданы в статике. Отраженное освещение особенно полезно для двух эффектов в 3D сцене: для отображения изменений при смене положения и имитации объектов из материалов с разными свойствами.
Отраженный свет может быть получен и без специализированного аппаратного процессора освещения, но при это производительность резко упадет. Наложение текстуры может быть использовано для некоторых отражающих световых эффектов, но если камера движется вокруг сцены, то карты среды должны все время пересчитываться, если аппаратная поддержка есть только наложения кубических карт отображения среды. Сферические карты отображения – общепринятая альтернатива, но этот способ чреват проблемами с производительностью и качеством изображения, делая невозможным получение интерактивной 3D среды.
Функции трансформации и освещения в графическом 3D конвейере традиционно решались с помощью возможностей доступных на рынке универсальных процессоров – для PC это значило использование центрального процессора. Это было вызвано тем, что для решения этих задач (T&L) требовались возможности процессора с плавающей точкой, а математический процессор уже в то время являлся обязательной составной частью универсальных процессоров (FPU). Стоимость реализации была естественным препятствием на пути добавления возможностей T&L в графические программы на персональных компьютерах.
Понятие стоимости было неактуально для экзотических Unix-станций, где цена неинтегрированных (дискретных) геометрических процессоров и процессоров освещения не имела значения из-за неограниченного бюджета. Как только за последующие 2 года затраты снизились, рабочие станции на Windows NT предоставили для бизнеса эти новые возможности, но с помощью составных графических плат расширения, стоящих тысячи долларов. Цены продолжали падать по мере того, как производители полупроводников умудрялись втискивать на один кристалл все больше и больше транзисторов. В 1999 году стало возможным отказаться от GPU с отдельными процессорами геометрии и освещения, т.к. теперь появилась возможность интегрировать эти процессоры на одном кристалле с другими компонентами графического 3D конвейера. Новейшие кремниевые технологии разрушили этот ценовой барьер и позволили nVidia интегрировать все компоненты конвейера в одном кристалле GPU и предложить его на рынке по приемлемой цене.
Математические требования к GPU четко определены. T&L вычисления целиком и полностью основаны на матричных вычислениях, специфичном перемножении 4×4 матриц и некоторых других векторных операциях. Строго определенное количество инструкций (операций) процессоров T&L весьма полезно для максимальной оптимизации их архитектуры для получения наивысшей кремниевой эффективности. Эта самая кремниевая эффективность делает легко предсказуемой и наивысшую производительность GPU. Это предположение основано на том, что буферы и конвейеры могут быть очень сильно оптимизированы в соответствии с крайне узким набором специфичных требований. Когда вычисления T&L возложены на ЦПУ, то производительность очень сильно колеблется, т.к. процессор вынужден делить эти вычисления с другими задачами общего характера. Большинство современных процессоров имеют специальные математические расширения команд (типа MMX, SSE, SSE2, 3DNow! и т.п.), но эти расширения также являются универсальными. Эти расширения предназначены для обработки функций мультимедиа (аудио, видео) и алгоритмов связи.
Хитовая 3D игра, запускаемая на GPU, должна быть большим, чем просто демонстрашкой прекрасной графики и «усладой для глаз». Она нуждается в изощренном искусственном интеллекте, реалистичной физике и целом комплексе игровых элементов. Потребность в мощном искусственном интеллекте в стратегиях и спортивных играх в до-GPU эпоху наделила персонажи убогим, плохо детализированным внешним видом. Разработчики были вынуждены жертвовать графическими возможностями игры в пользу задач искусственного интеллекта и физики, которые также возлагались на центральный процессор. GPU делает возможным для игроков в командные волейбол, футбол и баскетбол бегать, прыгать и смотреть как реальным игрокам. Моделирование реалистичной физики дополняет возможности 3D приложений, позволяя точно имитировать реальный мир. Объекты реального мира обладают моментом, точно так же должны его иметь и объекты 3D приложения. Эти функции сами по себе могут «заткнуть» современный топовый центральный процессор, ведь ЦПУ все еще выполняет и традиционные функции типа управления трафиком по шинам, запросы служб операционных систем и все запросы приложений. Эти функции не могут быть переложены на графический процессор, но функции GPU будут сняты с центрального процессора, а уже одно это значительно улучшает графическую производительность и производительность приложения в целом.
Пользователь PC – безоговорочный победитель
Приложение A
Операции при выполнении Трансформации и Освещения сходны, т.к. требуют повторения вычислений определенного набора математических функций много миллионов раз в секунду. Специфические математические требования, предъявляемые к GPU, описаны здесь, так что читатель может легко разобраться почему эти функции так сильно подвержены оптимизации и приспособлены для специализированных процессоров больше, чем для универсальных ЦПУ.
Операция трансформации – это операция умножения матрицы 4×4. Вектор, представляющий 3D данные, обычно содержит вершину или вектор нормали, помноженный на матрицу 4×4, называемую матрицей трансформаций и результат – трансформированный вектор. Чтобы это сделать, спецпроцессор трансформаций использует стандартную линейную алгебру для умножения матриц. На Рисунке 9 показан универсальный пример этой операции.
Перед тем, как трансформировать вектор, необходимо построить матрицу трансформаций. Эта матрица содержит всю необходимую информацию для конвертирования данных вектора в новую координатную систему. Промежуточная матрица создается для всех операций (масштабирование, вращение и смещение), которые должны быть выполнены над вектором, а затем все промежуточные матрицы перемножаются, чтобы получить единственную матрицу, которая и будет содержать итоговый результат всех операций. Эта одиночная матрица называется матрицей трансформаций и может многократно использоваться без перерасчета. Например, если матрица трансформаций уже создана, то она может с успехом использоваться для преобразования как одного вектора, так и целого миллиона. Эта способность к многократному использованию матрицы трансформаций весьма эффективно экономит время, необходимое для ее перерасчета.
Сперва может показаться, что достаточно матрицы размерностью 3×3, лишь потому, что это расчеты 3D графики. Четвертый компонент в исходном векторе – w. W используется в качестве коэффициента масштабирования при перспективной коррекции и дополняет матрицу трансформаций до размерности 4×4. Углубленное обсуждение параметра w лежит за границами этого документа.
Заметим, что количество математических операций для одного геометрического преобразования постоянно: 16 операций умножения и 12 операций сложения. Сама математика, требуемая для геометрических преобразований, так же весьма проста – используется только умножение и сложение.
Частью, относящейся к волшебству, при перемножении матриц во время геометрических преобразований является то обстоятельство, что масштабирование, вращение и трансляция – все эти операции могут выполняться параллельно, в один и тот же промежуток времени. Это делает производительность специализированного геометрического процессора величиной легко определяемой и более-менее постоянной. А это, в свою очередь, позволяет программистам реально оценить, на сколько их приложение будет «грузить» геометрию, чтобы сохранить достаточно приемлемый баланс производительность/качество.
Расчеты освещенности весьма требовательны к вычислительной мощности. Типичные расчеты освещенности вычисляют расстояние и направление между источниками света и объектами. Процессоры освещенности производят так же функции преобразования некоторых данных типа создания векторов нормали для треугольников и вершин, а так же «нормализации» этих векторов. Нормализация вектора – это процесс его преобразования в новый вектор с длиной равной единице по модулю и ориентированным так же, как и оригинальный вектор. Вектор «нормали» к вершине или треугольнику по определению – вектор, строго перпендикулярный треугольнику или вершине. Перпендикуляр к вершине определяется как перпендикуляр к поверхности, которую эта вершина описывает.
Эти векторы далее должны быть переработаны в скалярную величину расстояния и нормализованный вектор перед тем, как отправиться в процессор освещенности. Эти операции очень ресурсоемки, но совершенно необходимы потому, что представление разностных векторов как отдельных величин для расстояния и направления значительно упрощает последующие шаги в 3D конвейере. Вычисление расстояния – сложение квадратов величин x, y и z с последующим извлечением квадратного корня из этой суммы, как показано в Уравнении 1:
Нормализация вектора требует деления каждого из значений x, y и z на расстояние. Так что процессор освещения должен уметь как прибавлять, так и делить.
Аппаратный tl или многопроходный рендеринг что лучше
Сообщений в теме: 1497
#361 LAZER
Отправлено 26 Май 2016 — 20:40
Честно говоря, вообще не представляю как играть на контроллере в такие игры, как Mafia. The City of Lost Heaven и серию Grand Theft Auto. Имею ввиду именно те части, что выходили на PS2. Привык уже, что W,A,S,D — бегать, мышью поворачиваться. А как на PS2 управлять?
Intel Core i3 3240 | MSI B75MA-E33 | 8GB DDR3 Cricual | WD Blue 1TB | Plextor 120GB SSD | Samsung DVD RW | Sapphire Radeon RX 460 (4GB) | HIPRO 500W | Deepcool Theta 31 PWM | Zalman ZM-F2 FDB | world 727-10 |
#362 Генерал Максон
Отправлено 27 Май 2016 — 18:58
2-ая серия — Бегущий человек:
#363 Генерал Максон
Отправлено 29 Май 2016 — 09:39
3-я серия — Вечеринка с коктейлями:
#364 Генерал Максон
Отправлено 07 Июнь 2016 — 19:05
4-я серия — Непыльная работа:
#365 VatsOfGoo
Отправлено 07 Июнь 2016 — 20:50
Мне кажется или у тебя графичка не на максимуме?
Ученые расщепили атом. Теперь атом расщепляет нас.
#366 LAZER
Отправлено 08 Июнь 2016 — 01:44
Мне кажется или у тебя графичка не на максимуме?
Так оно и есть. Также сглаживание выключено или на минимуме.
Intel Core i3 3240 | MSI B75MA-E33 | 8GB DDR3 Cricual | WD Blue 1TB | Plextor 120GB SSD | Samsung DVD RW | Sapphire Radeon RX 460 (4GB) | HIPRO 500W | Deepcool Theta 31 PWM | Zalman ZM-F2 FDB | world 727-10 |
#367 Генерал Максон
Отправлено 08 Июнь 2016 — 04:54
Ох, ребята, прошу прощения, совсем забыл про тройную буферизацию и вертикальную синхронизацию — сделал. Следующая серия «Честная игра» будет уже с учётом этих настроек. А вот разрешение 1024 х 768 я оставлю. Посмотрите на скриншот — дальше уже идёт разрешение только для широкого экрана, а я, как ретро-геймер, предпочитаю формат 4:3.
Кстати, для чего нужны в самом низу пункты дополнительных настроек? Может что-нибудь из них тоже надо активировать?
#368 LAZER
Отправлено 08 Июнь 2016 — 14:45
Ох, ребята, прошу прощения, совсем забыл про тройную буферизацию и вертикальную синхронизацию — сделал. Следующая серия «Честная игра» будет уже с учётом этих настроек. А вот разрешение 1024 х 768 я оставлю. Посмотрите на скриншот — дальше уже идёт разрешение только для широкого экрана, а я, как ретро-геймер, предпочитаю формат 4:3.
Кстати, для чего нужны в самом низу пункты дополнительных настроек? Может что-нибудь из них тоже надо активировать?
У меня включены только «Clip always» и «Suspend when inactive».
Intel Core i3 3240 | MSI B75MA-E33 | 8GB DDR3 Cricual | WD Blue 1TB | Plextor 120GB SSD | Samsung DVD RW | Sapphire Radeon RX 460 (4GB) | HIPRO 500W | Deepcool Theta 31 PWM | Zalman ZM-F2 FDB | world 727-10 |
#369 VatsOfGoo
Отправлено 08 Июнь 2016 — 15:51
Кстати, для чего нужны в самом низу пункты дополнительных настроек? Может что-нибудь из них тоже надо активировать?
Suspend when inactive — чтобы игра во время сворачивания ставилась на паузу.
Clip always — настройка для видеокарт от ATi. Поэтому лучше включить.
Аппаратный TL — программная обработка освещения.
Короче, тебе нужно включить всё, кроме Многопроходного рендеринга.
Ученые расщепили атом. Теперь атом расщепляет нас.
#370 Генерал Максон
Отправлено 10 Июнь 2016 — 15:23
Ребята, как и обещал, новая серия с учетом применения вышеупомянутых настроек.
5-ая серия — Честная игра:
#371 Генерал Максон
Отправлено 23 Июль 2016 — 16:17
6-я серия — Сара; Пора привыкать:
#372 Генерал Максон
Отправлено 10 Август 2016 — 06:39
Обзавелись с женой новой видеокамерой.
Посему представляю вашему вниманию мини-обзор Super Famicom, дабы вы могли оценить качество картинки и голоса:
#373 Генерал Максон
Отправлено 12 Август 2016 — 13:18
И вот, наконец-то в моей ретро-коллекции появилась:
Super Nintendo Entertainmnet System региона NTSC-U
#374 LAZER
Отправлено 12 Август 2016 — 15:21
Intel Core i3 3240 | MSI B75MA-E33 | 8GB DDR3 Cricual | WD Blue 1TB | Plextor 120GB SSD | Samsung DVD RW | Sapphire Radeon RX 460 (4GB) | HIPRO 500W | Deepcool Theta 31 PWM | Zalman ZM-F2 FDB | world 727-10 |
#375 Генерал Максон
Отправлено 12 Август 2016 — 15:31
LAZER, спасибо большое!
Если устроит съёмка новой камерой со штатива экрана телевизора, то буду стараться
Как видишь, в данном обзоре, даже с экрана картинка нормальная.
#376 Istishia
Отправлено 13 Август 2016 — 00:55
Да ладно, видео не важно.. ну важно но не настолько) Голос приятный, слушать интересно
#377 Генерал Максон
Отправлено 13 Август 2016 — 05:28
Istishia, спасибо, очень приятно
#378 Генерал Максон
Отправлено 17 Август 2016 — 13:01
Живой летсплей игры Super Mario 64 (NTSC-J) само собой на консоли Nintendo 64.
Снимал камерой на телевизор, так как устройства захвата у меня нет, а эмулятором пользоваться не хочу — люблю играть на настоящем фирменном железе.
#379 Legend
Отправлено 17 Август 2016 — 16:42
От такого лютого мерцания экрана через пару минут из глаз начинает течь кровь. Неосмотрительно на мой взгляд.
#380 Генерал Максон
Отправлено 17 Август 2016 — 16:54
Как-то странно. Когда я снимал обзор на американскую Super Nintendo, ведь тоже снимал камерой на телевизор, однако не было мерцания.
Количество пользователей, читающих эту тему: 0
0 members, 0 guests, 0 anonymous users
Как оживить картинку в браузере. Многопроходный рендеринг в WebGL
Каждый, кто сталкивался с трехмерной графикой, рано или поздно открывал документацию на методы отрисовки, которые предполагают несколько проходов рендерера. Такие методы позволяют дополнить картинку красивыми эффектами, вроде свечения ярких пятен (Glow), Ambient occlusion, эффекта глубины резкости.
И «взрослый» OpenGL, и мой любимый WebGL предлагают богатую функциональность для отрисовки результатов в промежуточные текстуры. Однако управление этой функциональностью — довольно сложный процесс, в котором очень легко получить ошибку на любом из этапов, начиная от создания текстур нужного разрешения до именования юниформ и передачи их в соответствующий шейдер.
Чтобы разобраться, как правильно готовить WebGL, мы обратились к специалистам компании Align Technology. Они решили создать специальный менеджер для управления всем этим зоопарком из разных текстур, которым было бы удобно пользоваться. Что из этого получилось — будет под катом. Важно, что неподготовленного читателя, который никогда до этого не сталкивался с необходимостью организации многопроходного рендеринга, статья может показаться непонятной. Задача довольно специфическая, но и безумно интересная.
Чтобы вы понимали всю серьезность сиутации, коротко расскажу о компании. В Align выпускают продукт, который позволяет людям исправлять улыбки без традиционных брекетов. То есть их непосредственные потребители — это доктора. Это довольно ограниченная аудитория со специфическими запросами, накладывающими фантастические требования на надежность, производительность и качество пользовательского интерфейса. В свое время основным инструментом был выбран С++, но у него было серьезное ограничение: только десктопное приложение, только для Windows. Примерно два года назад начался переход на веб-версию. Возможности современных браузеров и стека технологий позволили быстро и удобно пересоздавать пользовательский интерфейс и адаптировать кодовую базу, которая до этого писалась почти 15 лет. Конечно, это привело к необходимости решать кучу задач на фронте и бэкенде, в том числе — к необходимости оптимизировать объемы данных и скорости загрузки. Этим задачам будут посвящены эта и следующие статьи.
И дабы дважды не вставать, я постараюсь не загромождать пост исходниками. То есть все, что входит в детали реализации и навевает тоску читателям кода, будет по возможности поскипано или сокращено до чистой, незамутненной идеи. Повествование будет вестись от первого лица, как это рассказывал Василий Ставенко — один из специалистов Align Technology, который согласился приоткрыть нам завесу тайны внутренней кухни WebGL-фронта.
Для начала стоило бы рассказать, что, собственно, мы хотели реализовать и что для этого требовалось. Наша специфика не подразумевает большое количество визуальных эффектов. Мы решили реализовать Screen Space Ambient Occlusion (или SSAO) и простенькую тень.
SSAO — это, грубо говоря, подсчет суммарного затенения в точке, окруженной другими точками. Вот суть этой идеи:
float light = 0; float deltaLight; for(int astep =0; astep fn(this)); let clear = options.clear ||
this.renderer.render(target.getScene(), target.getCamera(), target.framebuffer);
Таким образом, у нас нарисовался общий класс для наших проходов с вот таким вот интерфейсом:
class Pass< // Публичное: constructor(framebufferOptions = <>) <> // Детали реализации get clearOptions() get framebuffer() resize(w, h) // Это изменяет фреймбуфер setResolution(width, height) // это задает разрешение рисуемой текстуры. setResolutionWithoutScaling(width, height) // это изменяет разрешение текстуры в особых случаях. touchUniforms() prerender() postrender() installDependencies(dependenciesMap) getScene() getCamera() >
Как это должно работать
Для начала надо настроить наш менеджер. Для этого мы его инстанциируем и добавляем в него некоторое количество Pass-ов. Затем, когда нам надо нарисовать какой-то Pass на наш контекст, мы просто вызываем
Этот Pass должен отрисоваться на экране, а менеджер должен подготовить перед этим все зависимости. Поскольку мы хотим переиспользовать текстуры, наш менеджер будет проверять наличие уже отрисованных текстур, и чтобы он не решил, что текстуры с прошлого кадра — это те текстуры, которые можно не рисовать, мы перед началом отрисовки сбрасываем старые текстуры. Для этого у менеджера есть функция с соответствующим названием start.
Сумятицу в стройную схему внесла потребность рисовать на основной канвас полупрозрачных текстур. При блендинге не нужно стирать предыдущие результаты, да и сам блендинг надо настроить. В нашем случае подготовленные текстуры накладываются на изображение при конечной отрисовке именно блендингом. Процедура такая:
Видно, что небольшое отличие состоит в том, что буфер цвета не стирается, а все остальные буферы очищаются.
Если нам захочется вывести на экран какую-то промежуточную текстуру (например, в целях отладки), мы можем лишь слегка модифицировать render. Например, текстура с SSAO, которуя я привел выше, была отрисована вот таким кодом:
Реализация ScenePass
Теперь подробней остановимся на том, как именно рисовать наши проходы сцен в текстуры. Очевидно, что нам потребуется что-то, что умеет отрисовывать сцену, заменяя материал, и что-то, что будет отрисовывать все в экранных координатах.
Это весь класс. Получился довольно простым, поскольку почти всю функциональность удалось оставить в родителе. Как видите, я решил оставить overrideMaterial на тот возможный случай, когда мы сможем заменить материал на всей сцене разом в одну операцию присваивания, а не во время последовательной замены материала на всех подходящих объектах. Собственно, _prerender и _postrender — это и есть довольно умные заменители материала для каждого отдельного меша. Вот как они выглядят в нашем случае:
Scene.traverse — это метод THREE.js, который рекурсивно проходит по всей сцене.
Реализация ScreenSpacePass
ScreenSpacePass был задуман так, чтобы вытащить из шейдера максимум необходимой информации для того, чтобы работать с ним без лишнего бойлерплейта. Класс получился довольно сложным. Основная сложность пришлась на логику, которая обеспечивает сэмплирование, — то есть на установку правильных разрешений в текстуре. Пришлось заводить дополнительный метод, чтобы задавать разрешение текущего фреймбуфера в тех случаях, когда мы хотим отрисовать на экран, а не в текстуру. Пришлось пойти на этот компромисс между технической сложностью, ответственностью классов, количеством сущностей и временем, выделенным на задачу.
Автоматический поиск и установка юниформ помогли быстро найти такие проблемы, как опечатки в именах текстурных юниформ. В таких случаях GL может взять какую-то другую текстуру, и то, что получается у вас на экране, выглядит совершенно не так, как должно, и при этом у вас нет идей, почему.
Здесь исходник получился довольно большим, а класс — довольно умным. Впрочем видно, что большая часть кода как раз выясняет, есть ли в шейдере текстурные юниформы, и устанавливает их в качестве зависимостей.
Ну и в самом конце, я покажу, как мы этим пользовались. Application specific-сущность мы назвали EffectComposer. В его конструкторе создаем описанный менеджер и создаем ему пассы:
this.passManager = new PassManager(threeRenderer); this.passManager.addPass(‘downscalePositionSSAO’, new ScreenSpacePass(require(‘./shaders/passingFragmentShader.glsl’),
В качестве примера — содержимое файла passingFragmentShader.glsl:
precision highp float; uniform sampler2D positions; // это зависимость — нужно сначала отрисовать текстуру positions uniform vec2 resolution; void main()< vec2 vUv = gl_FragCoord.xy / resolution; gl_FragColor = texture2D(positions, vUv); >
Шейдер очень короткий — достать пиксель, который проинтерполируется, и тут же отдать его. Всю работу сделает линейная интерполяция в настройках текстуры (GL_LINEAR).
Теперь посмотрим, как будет отрисована positions.
Рабочая сцена нам нужна в других местах программы, поэтому EffectComposer не является ее владельцем, ему ее задают, когда надо.
Как видно, если кто-то сообщил нам об изменении сцены, EffectComposer создаст два Pass-a: один с настройками по умолчанию, а другой — с хитрой заменой материалов. Проходы сцены у нас не содержат каких-то хитрых зависимостей, они, как правило, рисуются сами по себе, однако описываемый подход позволяет это делать, если мы добавим в ScenePass несколько методов для того, чтобы добавлять зависимости. Потому что это неочевидно, какой именно материал из сцены захочет иметь отрисованную зависимость.
Несмотря на простоту использования в нашем случае, нам не удалось добиться полностью автоматической генерации пассов, основанных на шейдерах. Мне не хотелось добавлять в шейдеры маркеров, которые бы дополняли проходы прорисовки сцены дополнительными параметрами, такими как параметры вывода текстуры — GL_RGB, GL_RGBA, GL_FLOAT, GL_UNED_BYTE. Это бы, с одной стороны, упростило код, но дало бы меньше свободы переиспользования шейдеров. То есть эту настройку все равно пришлось описывать.
Стоит упомянуть, что мне пришлось еще реализовать маппинг зависимостей. Это оказалось полезно, если один шейдер мы хотим использовать в нескольких пассах и с разными входящими текстурами. В таком случае каждый пасс стал больше походить на функцию, поэтому у меня появилась идея, как это сделать немного «функциональнее».
Тем не менее, вся разработка оказалась весьма полезной. В частности, она позволяет без существенных сложностей добавлять нам любые эффекты в наш проект. Хотя мне лично больше всего нравится возможность легкого дебага изображений.