Потоковый рендеринг что такое
Серверный или клиентский рендеринг на вебе: что лучше использовать у себя в проекте и почему
Авторизуйтесь
Серверный или клиентский рендеринг на вебе: что лучше использовать у себя в проекте и почему
Разработчикам часто приходится принимать решения, которые повлияют на всю архитектуру приложения. Веб-разработчикам важно выбрать правильное место для реализации логики и рендеринга приложения. Это может быть непросто, так как сайт можно создать разными путями.
При выборе подхода для рендеринга нужно понимать разницу между возможными вариантами, чтобы не прогадать с производительностью. Сегодня мы разберёмся, в чём заключается эта разница.
Терминология
Отображение:
Производительность:
Серверный рендеринг
При серверном рендеринге в ответ на запрос на сервере генерируется весь HTML-код страницы. Это исключает необходимость дополнительных запросов данных со стороны клиента, так как сервер берёт всю работу на себя, прежде чем отправить ответ.
Такой подход позволяет добиться быстрой первой отрисовки и первой содержательной отрисовки. Выполнение логики страницы и рендеринг на сервере позволяют избежать отправки клиенту большого количества JavaScript, что приводит к меньшему времени до интерактивности. И это логично, ведь при серверном рендеринге пользователю отсылаются только текст и ссылки. Этот подход хорошо сработает на широком диапазоне устройств и сетевых условий, а также откроет возможности для интересных браузерных оптимизаций вроде потокового парсинга документа.
При использовании серверного рендеринга пользователям не нужно ждать завершения работы JavaScript, отнимающего ресурсы процессора, прежде чем они смогут начать работать с сайтом. Даже если нельзя избежать использования стороннего JavaScript, серверный рендеринг позволяет уменьшить количество вашего собственного JavaScript и даёт больше «бюджета» для всего остального. Однако у этого подхода есть один существенный недостаток: формирование страницы на сервере занимает определённое время, что может привести к большему времени до первого байта.
Ответ на вопрос «достаточно ли серверного рендеринга для моего приложения?» зависит от того, что вы создаёте. Сообщество давно дискутирует на тему правильного применения серверного рендеринга против клиентского, но важно помнить, что для одних страниц использовать серверный рендеринг можно, а для других — нет. Некоторые сайты успешно используют смешанный рендеринг. Netflix генерирует на сервере относительно статические лендинги и в то же время предварительно загружает JavaScript для страниц с высоким уровнем интерактивности, давая возможность быстрее загрузиться страницам, которые больше используют клиентский рендеринг.
Многие современные фреймворки, библиотеки и архитектуры позволяют рендерить одно и то же приложение как на клиенте, так и на сервере. Их возможности можно использовать и для серверного рендеринга, однако важно отметить, что архитектуры, в которых рендеринг происходит и на клиенте, и на сервере, являются отдельным классом решений со своими характеристиками производительности и недостатками. Пользователи React могут использовать для серверного рендеринга метод renderToString() или решения на его основе вроде Next.js. Пользователям Vue стоит обратить внимание на гайд Vue по серверному отображению или на Nuxt. Если ваш выбор — Angular, то посмотрите на Universal. Тем не менее в большинстве популярных решений присутствует какая-то форма гидратации, поэтому, прежде чем выбрать инструмент, разузнайте больше о используемом подходе.
Статический рендеринг
Статический рендеринг происходит на этапе сборки и предоставляет быструю первую отрисовку, первую содержательную отрисовку и время до интерактивности — при условии, что количество клиентского JavaScript ограничено. В отличие от серверного рендеринга здесь удаётся добиться стабильно быстрого времени до первого байта, так как HTML-код страницы не должен генерироваться на лету. Как правило, статический рендеринг подразумевает предварительное создание отдельного HTML-файла для каждого URL. Поскольку HTML-ответы созданы заранее, статический рендеринг можно развернуть на нескольких CDN, чтобы воспользоваться преимуществом кеширования.
Для статического рендеринга существуют самые разные решения. Инструменты вроде Gatsby разработаны так, чтобы создавать впечатление динамического рендеринга. Другие, вроде Jekyl и Metalsmith, принимают свою статическую природу и предлагают подход, основанный в большей степени на шаблонах.
Но у такого способа рендеринга есть один недостаток — необходимо заранее создать HTML-файлы для всех возможных URL. Это может быть очень сложно или даже невыполнимо, если вы не можете заранее сказать, какие URL возможны, или если у вас сайт с большим количеством уникальных страниц.
Пользователи React могут быть знакомы с Gatsby, статическим экспортом Next.js или Navi — все они делают использование компонентов удобнее. Однако важно понимать разницу между статическим рендерингом и пререндерингом: статически отрендеренные страницы не нуждаются в выполнении большого количества клиентского JS для интерактивности, в то время как пререндеринг улучшает первую (содержательную) отрисовку одностраничного приложения, которое должно быть загружено на клиент, чтобы страницы были действительно интерактивными.
Если вы не уверены, используется ли в решении статический рендеринг или пререндеринг, то попробуйте провести тест: отключите JavaScript и загрузите созданные страницы. У статически отрендеренных страниц функциональность по большей части останется на месте. У пререндеренных страниц может сохраниться базовая функциональность вроде ссылок, однако в целом страница будет не интерактивна.
Также можно устроить другую проверку: замедлите сеть с помощью инструментов разработчика и посмотрите, сколько JavaScript загружается, прежде чем страница становится интерактивной. Пререндерингу, как правило, требуется больше JavaScript для интерактивности, и обычно этот JavaScript более сложный, чем подход прогрессивного улучшения, используемый при статическом рендеринге.
Серверный рендеринг против статического
Серверное отображение не панацея — его динамическая природа может сопровождаться множественными вычислительными затратами. Многие решения с серверным отображением не используют технологию early flush и могут оттянуть время до первого байта или удвоить количество отправляемых данных (например, встроенное состояние, используемое JS на клиенте). В React метод renderToString() может быть медленным из-за синхронности и однопоточности. Для эффективной реализации серверного рендеринга может потребоваться найти решение для кеширования компонентов, разобраться с управлением потребления памяти, применить мемоизацию и не только. По сути вы заново обрабатываете/собираете одно приложение несколько раз — на сервере и на клиенте. Тот факт, что серверный рендеринг может показать что-то быстрее, вовсе не означает, что нужно проделать меньше вычислительной работы.
Серверный рендеринг создаёт HTML для каждого URL при необходимости, но такой подход может работать медленнее, чем простая отправка статического контента. Если вы готовы поработать дополнительно, то с помощью связки серверного рендеринга с HTML-кешированием вы сможете сильно уменьшить время рендеринга. Преимуществом серверного рендеринга является возможность извлекать больше актуальных данных и отвечать на более полный список запросов, чем это возможно при статическом рендеринге. Персонализированные страницы — яркий пример запроса, который не очень хорошо ладит со статическим рендерингом.
Клиентский рендеринг
Клиентский рендеринг подразумевает рендеринг страниц прямо в браузере с помощью JavaScript. Вся логика, получение данных, шаблонизация и маршрутизация обрабатываются на клиенте, а не на сервере.
Основной недостаток клиентского рендеринга заключается в том, что количество необходимого JavaScript обычно увеличивается вместе с ростом приложения. Ситуация ухудшается с подключением новых JavaScript-библиотек, полифиллов и прочего стороннего кода, который соревнуется между собой за вычислительные мощности и часто требует обработки, прежде чем содержимое страницы можно будет отобразить. Решениям с клиентским рендерингом, которые полагаются на большие JavaScript-бандлы, стоит рассмотреть сильное разделение кода и ленивую загрузку JavaScript — «загружайте только то, что вам нужно и только когда это нужно». Для решений с минимумом интерактивности или её отсутствием серверный рендеринг может предоставить более масштабируемое решение этих проблем.
Если вы создаёте одностраничное приложение, то, определив основные части пользовательского интерфейса, которые используются на большинстве страниц, вы сможете использовать кеширование оболочки приложения. В сочетании с Service Worker’ами это даст сильный прирост ощущаемой производительности при повторных посещениях.
Совмещение серверного и клиентского рендеринга с помощью регидратации
Универсальный рендеринг (или просто «SSR») пытается устранить недостатки серверного и клиентского рендеринга, используя оба подхода. Навигационные запросы вроде полной загрузки или перезагрузки страницы обрабатываются сервером, который рендерит приложение в HTML, затем JavaScript и данные, используемые для рендеринга, встраиваются в итоговый документ. При правильной реализации время первой содержательной отрисовки будет как при серверном рендеринге, а повторный рендеринг будет производиться на клиенте с помощью техники, называемой (ре)гидратацией. Это новое решение, тем не менее не лишённое определённых проблем с производительностью.
Основной недостаток универсального рендеринга с регидратацией заключается в том, что такой подход может очень негативно повлиять на время до интерактивности даже при улучшении первой отрисовки. Страницы часто выглядят обманчиво готовыми и интерактивными, но по факту не могут никак реагировать на действия пользователя до выполнения JS на стороне клиента и присоединения обработчиков событий. Это может занять несколько секунд или даже минут на мобильных устройствах.
Возможно, вы и сами сталкивались с таким — страница уже какое-то время выглядит загруженной, но нажатия на элементы не дают эффекта. Это сильно удручает: «Почему ничего не происходит? Почему я не могу скроллить?».
Проблема регидратации: одно приложение по цене двух
Из-за JavaScript проблемы регидратации могут быть похуже, чем отложенная интерактивность. Для того чтобы клиентский JavaScript мог, не прибегая к новому запросу всех данных, использованных сервером для рендеринга HTML, продолжить работу с того места, где прекратил работу сервер, текущие решения на основе универсального рендеринга обычно сериализуют данные для интерфейса в документ в виде тегов
Рендеринг в веб
о переводе
Наше понимание в этой области основано на нашей работе с Chrome, и контактировании с большими сайтами в течение последних нескольких лет. В общем, мы хотим вдохновить разработчиков рассмотреть использование серверного рендеринга или статического рендеринга с полноценной регидратацией.
Чтобы лучше понимать архитектуры, из которых мы выбираем, когда принимаем решение, нам необходимо иметь четкое понимание каждого подхода и последовательную терминологию, которую мы будем использовать, когда говорим о них. Различия между этими подходами помогают проиллюстрировать компромиссы при рендеринге в вебе через призму производительности.
Терминология
Рендеринг
Rehydration (регидратация): «загрузка» JavaScript отображениий на клиенте таким образом, чтобы они повторно использовали отрендеренное на сервере DOM-дерево и данные HTML-а
Prerendering (пре-рендеринг): выполнение клиентского приложения во время сборки для захвата его начального состояния в виде статического HTML.
Performance
Server Rendering (Серверный рендеринг)
Серверный рендеринг генерирует полный HTML страницы на сервере в ответ на навигацию. Это позволяет избежать дополнительных проходов для получения данных и шаблонов на клиенте, так как это выполняется до того, как браузер получает ответ..
Серверный рендеринг обычно даёт быстрый First Paint (FP) и First Contentful Paint (FCP). Выполнение логики страницы и её рендеринг на сервере позволяют избежать отправки большого количества JavaScript клиенту, что помогает достичь быстрого Time to Interactive (TTI). Это имеет смысл потому, что при серверном рендеринге вы на самом деле просто посылаете текст и ссылки в браузер пользователя. Такой подход может хорошо работать для широкого спектра устройств и сетевых условий и открывает интересные возможности для оптимизации браузера, например можно выполнять разбор потоковых (streaming) документов.
При серверном рендеринге пользователи вряд ли будут вынуждены ждать, пока CPU-зависимый JavaScript будет выполнен, прежде чем они смогут использовать ваш сайт. Даже когда стороннего JS не избежать, использование серверного рендеринга для уменьшения собственных JS costs (JS затрат) может дать вам больше «budget» (бюжета) для остального. Однако, есть один основной недостаток такого подхода: генерация страниц на сервере занимает время, что часто может привести к замедлению Time to First Byte (TTFB).
Достаточно ли серверного рендеринга для вашего приложения, во многом зависит от того, какое приложение вы строите. Существует давняя дискуссия о правильности применения серверного рендеринга вместо клиентского рендеринга, но важно помнить, что вы можете использовать серверный рендеринг для одних страниц, а для других нет. Некоторые сайты с успехом переняли гибридный рендеринг. Netflix делает серверный рендеринг своих относительно статических страниц, в то время как делает prefetching JS для страниц с тяжелым взаимодействием, давая этим более тяжелым отрендеренным на клиенте страницам больше шансов на быструю загрузку.
Многие современные фреймворки, библиотеки и архитектуры позволяют отрисовывать одно и то же приложение как на клиенте, так и на сервере. Эти инструменты могут быть использованы для Server Rendering, однако важно отметить, что архитектуры, где рендеринг происходит как на сервере, так и на клиенте, являются собственным классом решений с очень различными характеристиками производительности и компромисами. React пользователи могут использовать для серверного рендеринга renderToString() или решения, построенные на нем, такие как Next.js. Пользователи Vue могут ознакомиться с руководством по серверному рендерингу Vue или познакомиться с Nuxt. В Angular есть Universal. Однако большинство популярных решений используют ту или иную форму гидратации (hydration), поэтому перед выбором инструмента следует ознакомиться с используемыми подходами.
Static Rendering (Статический рендеринг)
Решения для статического рендеринга бывают разных форм и размеров. Такие инструменты как Gatsby разработаны для того, чтобы разработчики чувствовали, что их приложение отрисовывается динамически, а не генерируется на этапе сборки. Другие, такие как Jekyll и Metalsmith, принимают их статическую природу, предоставляя подход более заточенный на шаблоны.
Одним из недостатков статического рендеринга является то, что отдельные HTML-файлы должны быть сгенерированы для каждого возможного URL. Это может быть сложно или даже невозможно, когда вы не можете предсказать, какими будут эти URL заранее, или если на сайте большое количество уникальных страниц.
Если вы не уверены, является ли решение статическим рендерингом или пре-рендерингом, попробуйте такой тест: отключите JavaScript и загрузите созданные веб-страницы. У статически отрендеренных страниц бОльшая часть функционала все равно будет существовать и без включённого JavaScript. У пре-рендеренных страниц все еще может быть некоторая базовая функциональность, такая как ссылки, но бОльшая часть страницы будет неживой.
Серверный рендеринг против статического
Серверный рендеринг генерирует HTML по требованию для каждого URL, но это может быть медленнее, чем просто обслуживание статически отрендереного контента. Если вы готовы сделать дополнительные усилия, то серверный рендеринг + [HTML кеширование] (https://freecontent.manning.com/caching-in-react/) может значительно сократить время серверного рендеринга. Положительной стороной серверного рендеринга является возможность получать более «живые» данные и отвечать на более полный набор запросов, чем это возможно при статическом рендеринге. Страницы, требующие персонализации, являются хорошим примером типа запроса, который плохо работает со статическим рендерингом.
Серверный рендеринг также может представлять интересные решения при построении PWA. Лучше ли использовать full-page service worker кеширование, или просто рендерить на сервере отдельные фрагменты контента?
Client-Side Rendering (CSR)
Рендеринг на стороне клиента (CSR) означает рендеринг страниц непосредственно в браузере с использованием JavaScript. Вся логика, сбор данных, шаблонирование и маршрутизация обрабатываются на клиенте, а не на сервере.
Для тех, кто создает одностраничное приложение, определение основных частей пользовательского интерфейса, разделяемого большинством страниц, означает возможность применить технику Application Shell caching. В сочетании с service workers это может драматически повысить воспринимаемую производительность при повторных визитах.
Комбинация серверного рендеринга и клиентского через регидратацию
Часто называемый Universal Rendering или просто «SSR», этот подход пытается сгладить компромиссы клиентского и серверного редеринга, делая и то, и другое. Навигационные запросы, такие как полная загрузка страницы или перезагрузка, обрабатываются сервером, который рендерит приложение в HTML, затем JavaScript и данные, используемые для рендеринга, встраиваются в результирующий документ. При тщательной реализации, это даёт быстрый FCP (First Contentful Paint) такой же, как Server Rendering, а далее «усиливает это» путем рендеринга опять же на клиенте с помощью техники, называемой (re)hydration ((ре)гидратация). Это новое решение, но оно может иметь некоторые существенные недостатки в производительности.
Основной недостаток SSR с регидратацией (rehydration) заключается в том, что она может оказать значительное негативное влияние на TTI (Time To Interactive), даже если она улучшает FP (First Paint). SSR-страницы часто выглядят обманчиво полностью загруженными и интерактивными, но на самом деле не могут реагировать на ввод, пока не будет выполнен JS на стороне клиента и не будут прикреплены обработчики событий. Это может занять секунды или даже минуты на мобильном устройстве.
= Проблема регидратации: Одно приложение по цене двух
Проблемы с регидратацией часто могут быть хуже, чем задержка интерактивности из-за JS. Для того, чтобы JavaScript на стороне клиента мог точно «определить» («pick up») то место, где остановился сервер, без необходимости повторно запрашивать все данные, использованные сервером для рендеринга этого HTML, текущие SSR решения обычно сериализуют ответ из зависимых данных UI в документ в виде тегов script. Полученный HTML-документ содержит высокий уровень дублирования:
Как вы видите, сервер возвращает описание пользовательского интерфейса приложения в ответ на навигационный запрос, но также возвращает исходные данные, использованные для составления этого интерфейса, и полную копию реализации интерфейса, которая затем загружается на клиенте. Только после того, как bundle.js завершит загрузку и выполнение, этот пользовательский интерфейс станет интерактивным.
Показатели производительности, собранные с реальных веб-сайтов, использующих SSR регидратацию, указывают на то, что их использование должно приводить в уныние. В конце концов, причина сводится к Пользовательскому Опыту: очень легко оставить пользователей в «жуткой долине».
Но всё же надежда на SSR с регидратацией есть. В краткосрочной перспективе, только использование SSR для высоко кешируемого содержимого может уменьшить задержку TTFB (Time to First Byte), давая результаты, схожие с пре-рендерингом. Регидратация инкрементальная, прогрессивная или частичная, может быть ключом к тому, чтобы сделать эту технику более жизнеспособной в будущем.
Потоковый серверный рендеринг и прогрессивная регидратация
Серверный рендеринг за последние несколько лет претерпел ряд изменений.
= Частичная регидратация
Частичная регидратация оказалась трудной для осуществления. Этот подход является продолжением идеи прогрессивной регидратации, когда отдельные части (компоненты / виджеты / деревья), подлежащие прогрессивной регидратации, анализируются, а те, которые обладают низкой интерактивностью или не обладают реактивностью помечаются. Для каждой из этих наиболее статических частей соответствующий код JavaScript затем трансформируется в инертные ссылки и декоративную функциональность, уменьшая их влияние на стороне клиента до почти нулевого уровня. Подход, основанный на частичной гидратации, имеет свои собственные проблемы и компромиссы. Он создает некоторые интересные вызовы для кеширования, а навигация на стороне клиента означает, что мы не можем иметь HTML рендерящийся на сервере для инертных частей приложения и доступный без полной загрузки страницы.
= Трисоморфный рендеринг (Trisomorphic Rendering)
Если service workers, являются подходящим вариантом для вас, то «трисоморфный» рендеринг также может быть вам интересен. Это метод, при котором вы можете использовать потоковый серверный рендеринг для начальных/не-JS навигаций, а затем попросить ваш service worker взять на себя рендеринг HTML для навигации после того как он будет смонтирован. Это может поддерживать кешированные компоненты и шаблоны в актуальном состоянии и позволяет использовать навигацию в стиле SPA для рендеринга новых UI-частей в той же сессии. Такой подход лучше всего работает, когда вы можете поделиться одним и тем же шаблоном и кодом маршрутизации между сервером, клиентской страницей и service worker.
SEO соображения
Команды часто учитывают влияние SEO при выборе стратегии для рендеринга в вебе. Серверный рендеринг часто выбирается для обеспечения поисковым роботам возможности лёгкого «полного поиска». Поисковые роботы могут понимать JavaScript, но часто существуют ограничения, о которых стоит знать в части того как они рендерят. Рендеринг на стороне клиента может работать, но часто не без дополнительного тестирования и трудной работы. В последнее время динамический рендеринг также стал вариантом, заслуживающим внимания, если ваша архитектура в значительной степени ориентирована на клиентский JavaScript.
В случае сомнений, инструмент Mobile Friendly Test бесценен для проверки, что выбранный вами подход делает то, что бы вы хотели. Он показывает визуальный предварительный просмотр того, как какую-либо страницу видет поисковый робот Google, сериализованный HTML контент, найденный (после выполнения JavaScript), и любые ошибки, обнаруженные во время рендеринга.
Заключение.
При принятии решения о подходе к рендерингу, измеряйте и понимайте, каковы ваши «узкие места». Подумайте, может ли статический рендеринг или серверный рендеринг дать вам хотя бы 90% возможностей. Совершенно нормально обычно отправлять HTML с минимальным количеством JS, чтобы получить интерактивный опыт. Вот удобная инфографика, показывающая спектр возможностей в разрезе сервер-клиент:
Благодарности
Спасибо всем этим людям за отзывы и вдохновение:
Jeffrey Posnick, Houssein Djirdeh, Shubhie Panicker, Chris Harrelson, and Sebastian Markbåge
VJ Софт
Для многих людей слово «рендеринг» прочно ассоциируется с другим: «ожидание». Для небольшого же количества людей слово «рендеринг» означает комплекс математических операций с широким диапазоном возможных результатов. Эта статья поможет людям, далеким от программирования, понять, что же происходит внутри компьютера во время рендеринга. Мы рассмотрим несколько способов рендеринга и примеры их применения на практике.
Большинство 3D моделлеров, художников и аниматоров плохо представляют как проходит рендеринг, и чем занимается программа рендерер в процессе работы. Программа рендерер рассматривает 3D сцену с математической точки зрения, вычисляет, как должна выглядеть сцена и затем создает итоговое изображение. Мы все знаем, что разные программы используют разные технологии рендеринга – трассировка лучей (raytrasing), ретуширование (shading) и сглаживание контурных неровностей (antialiasing), для достижения максимальной похожести искусственного изображения на реальную жизнь. Мы также прекрасно знаем, что чем сложнее сцена и выше качество выходного изображения, тем дольше длится процесс рендеринга. Возможно, вы также слышали такой термин, как «потоковый рендеринг» (rendering pipeline). Но, в сущности, мало кто задумывался, каким образом происходит процесс рендеринга и от чего зависит конечный результат. Мы думаем, вам интересно будет узнать об особенностях различных рендереров, их возможностях и различиях.
Начнем с цифр – вы наверное не догадывались, но существует более 500 (пятьсот) различных программ для рендеринга. Одни из них встроены в пакеты 3D моделирования, другие поставляются как отдельные продукты, одни могут выполнять огромное число задач, другие созданы для специфических целей. Существуют рендереры, созданные специально для определенных индустрий (например, для военных целей), для определенного оборудования (Амига), для определенных операционных систем (Линукс), и других, иногда самых неожиданных целей (3D аудио). Кроме того, существует некоторое количество бесплатных рендереров, созданных энтузиастами.
Совершенно необязательно знать про все эти системы рендеринга. Но в зависимости от работы, которую вам необходимо выполнить, вам, возможно, понадобятся некоторые знания, касающиеся различных программ рендеринга. Например, если вы разрабатываете сцены для игровой индустрии, вам необходимо знать возможности real-time рендерера, на основе которого будет работать игра.
Большинство рендереров делятся на две категории: real-time и non-real-time. Кроме того, все рендереры можно разделить по принципу используемых технологий – scan-line и raytrace. Мы рассмотрим основных представителей этих категорий и их различия, чтобы вы смогли самостоятельно выбрать наиболее для вас подходящий.
Потоковый рендеринг (Rendering Pipeline)
Потоковый рендеринг основывается на четырех уровнях.
Все объекты 3D сцены четко определены в пространстве, до того, как вы помещаете объект в сцену, у него уже есть собственное геометрическое описание: длина, высота, ширина и глубина, но он пока никак не связан с другими объектами. В этот этап также может входить и процесс tessellation (когда обсчитываемые поверхности трансформируются в полигоны). Тут нужно быть осторожным, т.к. если вы используете NURBS и поверхности Безье – точность выполнения tessellation виляет на окончательные результаты.
Когда вы помещаете объект в сцену, он приобретает дополнительные геометрические описания, теперь у него есть точная позиция и ориентация по отношению к другим объектам сцены. На этом этапе назначаются параметры поверхностей объектов и устанавливается освещение. Также объектам могут быть присвоены анимационные ключи.
Когда в сцене появляется камера, все объекты приобретают новый параметр – ориентация и местоположение по отношению к камере. На этой стадии все полигоны проверяются на предмет видимости, полигоны, не видимые камерой игнорируются. Этот процесс называется отсеиванием невидимых поверхностей (backface cutting). Камере также могут быть присвоены анимационные атрибуты.
Далее, все объекты трансформируются с точки зрения конечного изображения. Сначала, в зависимости от настроек камеры (фокусное расстояния, поле зрения и т.п.) формируется визуальный коридор. Полигоны полностью за пределами визуального коридора игнорируются, лежащие на границе – усекаются. На этом этапе выполняется множество визуальных трюков, чтобы компенсировать искажение перспективы (более удаленные вещи кажутся меньше и т.д.).
Все эти этапы – это части «технического» рендеринга и большинство пакетов 3D-моделирования позволяют выполнять их в реальном времени и приступать к финальной стадии только после нажатия кнопки «RENDER».
В то время как начальные этапы потока довольно незамысловаты (чистая математика), последняя стадия может быть выполнена огромным количеством способов, приемов и трюков, призванных ускорить процесс, но в тоже время сделать сцену максимально реальной. К сожалению, многие приемы, используемые для ускорения процесса или достижения определенного визуального эффекта ведут к появлению проблем, которые решаются с помощью новых приемов и трюков (со своими проблемами) – и так далее.
Например, рендереры, основанные на принципе Radiosity, берут почти готовую сцену и анализируют количество света, отраженного от других поверхностей, с учетом изменения его спектра, этот свет в свою очередь отражается от поверхности и падает на другую…Эти вычисления повторяются снова и снова. Когда вычисления закончены, каждая поверхность окрашивается и ретушируется в соответствии с результатами вычислений. Главной проблемой такого способа является то, что для ограничения времени выполнения (иначе вычисления длились бы бесконечно), обсчет ведется в соответствии с определенным алгоритмом, но именно в результате этого некоторые поверхности могут быть выключены из общего процесса и окрашены некорректно.
Тем не менее, такой способ рендеринга дает прекрасные результаты. Но Radiosity, который прекрасно подходит для неподвижных сцен, мало пригоден для рендеринга анимаций. В силу особенностей данного принципа, при рендеринге движущихся объектов возможно появление мерцания.
Scanline рендеринг
Как я уже сказал ранее, существует два основных подхода к процессу рендеринга: scanline и raytracing. Что же представляет из себя Scanline рендеринг? Предположим, что нам необходимо получить изображение разрешением 300Х200. Программа проводит воображаемую линию через каждый пиксель, вычисляя, какие полигоны лежат на пути этой линии и вычисляет необходимый цвет пикселя, в зависимости от того, какие текстуры и цвета были назначены полигонам, встретившимся на пути этой воображаемой линии. Затем берется следующий пиксель, затем следующий – и так до конца.
Основной проблемой этого способа является отделение видимых полигонов от невидимых. В первых поколениях такого рода рендереров процесс вычисления полигонов начинался с самой дальней точки от зрителя и каждый новый полигон закрашивал предыдущий. Такой подход далек от идеала из-за множества ненужных операций. Чтобы решить эту проблему используется Z-буфер. Программа вычисляет все полигоны, лежащие на пути воображаемой линии и назначает каждому полигону Z-значение в зависимости от его удаленности от экрана. Когда настает время рендеринга, обсчитываются только полигоны с наименьшим Z-значением – остальные просто отбрасываются. Такой способ позволяет существенно ускорить процесс рендеринга, но имеет и существенные недостатки, которые будут рассмотрены ниже.
Raytrace рендеринг
Подобно Scanline рендереру, Raytrace рендерер начинает с вычисления воображаемой линии от одного пикселя (кроме того, существует инверсный рендеринг, когда вычисления начинаются от источника света и рендеринг использованием обоих принципов). Когда воображаемая линия встречает на своем пути полигон, случаются три вещи. Сначала вычисляется цвет и яркость на основе прямого освещения источниками света, затем вычисляются углы отражения и преломления (reflection/refraction). На основе параметров отражения/преломления данного полигона луч раздваивается и двигается по двум новым направлениям. Если любой из этих лучей встретит полигон, он раздваивается снова – и так до определенного момента, когда луч либо уйдет за пределы сцены, либо встретит источник света, либо количество отражений/преломлений достигнет определенного установленного числа (recursion level). Когда все лучи закончат свое движение, вычисляется окончательное значение пикселя.
Инверсные трассировщики лучей начинают вычисления от источника света, с огромного количества лучей света, отражающихся от объектов сцены, которые возможно пройдут через нужный пиксель и достигнут зрителя.
Мы думаем, вы представляете себе, с какой легкостью такие способы вычислений могут поглотить миллиарды вычислений и занять огромное количество времени. Создатели таких рендереров обычно дают пользователю возможность точно указать, сколько отражений луча обсчитывать. Иногда пользователь может пользоваться только уже заранее установленными настройками типа good; better; best.
Выгодой такого способа является точность обсчета отражений и преломлений – свет отражается от зеркала либо проходит через воду именно так, как это происходит в реальной жизни. Такой способ рендеринга позволяет точно вычислять тени. Когда луч встречает полигон, программа пытается провести от этого полигона прямой луч к источнику света, если это невозможно – полигон затеняется.
Основные недостатки – огромное число вычислений и исключение из обсчета определенных свойств света (отраженное освещение). В природе нет абсолютно черных теней, т.к. весь мир наполнен отраженным освещением. Многие рендереры пытаются избавиться от этих недостатков двумя путями: они либо добавляют общее освещение (global illumination), которое освещает всю сцену, либо представляют все объекты сцены как отдельные источники света, способные излучать слабый свет.
Ретуширование
Все алгоритмы ретуширования пытаются эмулировать то бесконечное число способов, какими луч света реагирует на поверхность в реальном мире. Отражения (reflections), отражение/поглощение света (transmission/absorbtion), рассеивание света (diffraction), преломление света (refraction), смешивание света различных источников (interference). Проще говоря, алгоритм ретуширования используется для вычисления вида поверхности при разном освещении. Самым простым алгоритмом является Flat shading – одноцветный полигон. Небольшим шагом в сторону улучшения качества работы этого алгоритма является его способность изменять оттенок цвета в зависимости от угла, под которым свет падает на поверхность. Таким образом, мы можем произвести простейшую трассировку лучей – проводится воображаемая линия сквозь пиксель экрана пока она не натолкнется на полигон. Затем проводим следующую линию от этого полигона к источнику света и вычисляем получившийся угол. Когда угол вычислен, программа рендерер просто применяет нужную формулу и вычисляет цвет пикселя. Но подобная техника не рассчитана на вычисление теней, т.к. она работает только с одним источником света и не может учитывать освещение данного полигона другими источниками света. К счастью, большинство рендереров решают эту проблему тем или иным способом и нам не придется напрямую сталкиваться с этой проблемой.
Real-Time против Non-Real-Time
Реал-тайм рендереры (основанные чаще всего на принципе scanline) созданы в первую очередь для скорости, а не для качества. Чаще всего их можно встретить в играх, различных симуляторах реального времени или в пакетах 3D моделирования. Основной выгодой использования принципа Scanline – это скорость, но для того, чтобы эмулировать различные визуальные эффекты она мало подходит. Для их реализации используются различные трюки. Чтобы эмулировать поведение света, сцена просчитывается в несколько проходов.
Например, если необходимо создать эффект объемного дыма, создается текстура дыма и накладывается на анимированную плоскую поверхность, но если нужно посмотреть на этот дым, скажем, сквозь оконное стекло, сцену необходимо просчитать дважды – первый раз для создания дыма, и второй – чтобы наложить на нее текстуру окна. Разумеется, если слишком увлечься созданием эффектов, то это приведет к существенной потере скорости.
Реал-тайм рендереры используют множество трюков для достижения высокого качества изображения при сохранении высокой скорости. Z-буфер уже не используется. Для определения невидимых объектов используется другая техника, основанная на иерархическом положении объектов в сцене. Эти принципы применяются в таких играх, как Doom, Quake и др. Текстуры, в основном те, которые используются для стен, обсчитываются заранее с разных точек зрения и сохраняются в отдельных файлах. Затем в реальном времени просчитывается позиция игрока и накладываются наиболее подходящие текстуры. Другие рендереры (как в Quake 3 Arena) используют другую технику Color by Vertex. Все эти техники призваны ускорить процесс рендеринга, но в тоже время существенно ограничивают художников и моделлеров в осуществлении их фантазии.
Если вы создаете 3D сцену для игры, либо для другой программы где будет использован реал-тайм рендерер, вы должны принимать во внимание все ограничения такого типа рендерера и знать способы обхода этих ограничений – но это уже тема для отдельной беседы.
Не все Scanline рендереры работают в реальном времени. Рендереры основанные на этом принципе также доминируют в индустрии кино и телевидения. Всем известные Pixar’s RenderMan и Electric Image’s Camera основаны на принципе Scanline. Есть две причины, по которым эта система используется в этих индустриях, первая – высокий уровень фотореализма не так важен, т.к. кадр появляется на экране на доли секунды, и вторая это скорость. Когда мы имеем дело с теми разрешениями, которые используются в кино-теле индустрии, даже оснащенные супермощной техникой студии рендеринга работают на пределе, и использование технологии трассировки лучей может добавить многие месяцы работы.
Нон-реал-тайм рендереры, такие, какие используются в Softimage, NewTek LightWave или Discreet 3D Studio MAX, направлены на создания высоко фотореалистичных изображений (естественно теряя при этом в скорости). Все они в основном базируются на технологии трассировки лучей. Такие рендереры могут также выпускаться отдельно от пакетов моделирования. Рендереры, основанные на технологии трассировки лучей, это идеальный инструмент для достижения высококачественных изображений, особенно для неподвижных изображений, когда зрители могут тщательно рассмотреть работу и выявить возможные недостатки. Такие рендереры могут с легкостью обрабатывать сложные сцены с большим количеством источников света и использованием отражающих/преломляющих поверхностей.
Следует отметить, что большинство систем рендеринга на сегодняшний день используют обе технологии параллельно и занимаются трассировкой лучей только в том случае, если это необходимо (обусловлено присутствующими в сцене материалами)
Посмотрим на вещи беспристрастно
Мы уже выяснили, что работа всех программ рендеринга состоит из стандартных этапов. Чем же отличаются друг от друга разные программы? Было проведено исследование, чтобы выяснить, чем же отличаются программы рендеринга разных компаний. Большинство компаний, разумеется, не желает делиться секретами своих технологий, но кое-что все же удалось узнать.
Разумеется, каждая компания утверждает, что ее продукт уникален, и что недостатки качества изображения зависят от пользователя, не удосужившегося настроить программу и воспользовавшегося предустановленными настройками (default).
По заявлению одного из специалистов компании NewTek, люди просто привыкли, что разным продуктам присуще разное качество конечных изображений. Например продукты Alias и LightWave выдают более органичные изображения, тогда как Max лучше работает с такими материалами как пластик и металл. Все это результат лени, и нежелания тратить время на получение нужного результата. При определенных усилиях можно получить совершенно одинаковые результаты в разных программах.
Кроме того, каждая компания заявляет, что именно ее рендерер является самым быстрым. Но такие заявления очень трудно доказать (впрочем как и опровергнуть), так как для этого необходимо создать равные условия работы – а это довольно сложно, учитывая, что программы работают с разными пакетами 3D моделирования. Что можно сказать наверняка, так это то, что Pixar RenderMan и Electric Image Camera работают более быстро, чем их аналоги, основанные на трассировке лучей.
В методе трассировки лучей довольно мало способов ускорить процесс. Первый и главный способ – мультипроцессорная обработка сцены, такая функция встроена практически во все популярные пакеты 3D- моделирования и рендереры. Большинство из них также поддерживают сетевой рендеринг. Все зависит от того, сколько вы готовы платить – LightWave распространяет эти функции бесплатно, в других пакетах необходимо покупать отдельную лицензию на каждую машину, участвующую в рендеринге.
По мнению многих профессионалов Maya обладает самыми лучшими инструментами для анимации мягких тел. Эти инструменты позволяют данной программе создавать очень реалистичную анимацию ткани и воды. Еще одна уникальная черта данной программы – интерактивный рендерер, позволяющий практически мгновенно видеть результаты работы, включая освещение, текстуры, линзы и другие эффекты.
NewTek LightWave
Считается, что LightWave обладает одним из лучших рендереров. По заявлениям NewTek, их продукт является самым быстрым и точным (впрочем, так говорят все компании о своих продуктах). LightWave использует 96-битную глубину цвета. Новая версия пакета будет обладать способностью обсчитывать анимацию методом Radiosity (впервые на рынке подобных продуктов). Эта программа также поддерживает мультипроцессорный и сетевой рендеринг и выборочную трассировку лучей.
Pixar RenderMan
RenderMan является основным рендерером кино-теле индустрии. Его основным преимуществом является скорость и способность обсчитывать сцены высокой сложности (с многими тысячами полигонов). Разработчики данной программы также гордятся качеством выполнения antialiasing и motion blur, точностью настроек камеры.
RenderMan – это scanline рендерер, поэтому для работы ему требуется набор шейдеров (shader) для создания реалистичных световых эффектов. Разработчики программы создали целый язык, на котором можно программировать шейдеры, но это довольно сложно и многие компании нанимают специалистов для программирования шейдеров. Разумеется Pixar обладает стандартной библиотекой шейдеров которую вы можете использовать, кроме того, существует много отдельных студий, занимающихся их созданием.
RenderMan – это только программа рендеринга без возможности моделирования. Вам придется создавать и анимировать сцены в других программах, а затем передавать их в RenderMan для финального рендеринга. Для этой цели существуют дополнительные программы.
Electric Image Camera
Данная программа является аналогом RenderMan и также ориентирована на кино-теле индустрию. Ее показатели и принцип работы практически совпадает с RenderMan. Единственное различие – программирование шейдеров не является таким сложным процессом и требует лишь знаний C и C++.
Discreet 3D Studio MAX
Max – это рабочая лошадка 3D индустрии во всех областях: рендеринг, моделирование, анимация. Это, возможно, самая гибкая программа т.к. вся ее работа основана на плагинах. Таким образом вы можете добавить в нее те функции, которые вам необходимы и настроить программу под ваши нужды. В этом Max далеко обогнал всех своих конкурентов. Таким образом, если вам не нравится работа встроенного рендерера, вы можете с легкостью поменять его на дюжину других, которых он поддерживает.
Softimage Mental Ray
Данная программа использует комбинацию scanline и raytracing. Также есть возможность программировать свои собственные шейдеры (если вы знаете C или C++). Если такая задача вас пугает – существует множество уже готовых.
Что нас ждет в будущем
Какие же улучшения в области рендеринга нас ждут в будущем? Phil Miller, исполнительный менеджер Max говорит: «Скорость – это необязательно следующий шаг. Мы уже знаем как повторить большинство тех образов, которые мы видим в реальной жизни. Мы можем повторить 95% эффектов реальной жизни, но каждый новый уровень реализма требует удвоения количества расчетов и при этом только слегка приближает нас к реальности. Возможно теперь, когда производительность процессоров так выросла, мы сможем осуществить это».