Готовый перевод Ogre3D Basic Tutorials / Базовые туториалы Ogre3D: Basic Tutorial 2: Cameras, Lights, and Shadows

Внимание! Этот перевод, возможно, ещё не готов, так как модераторы установили для него статус «перевод редактируется»

ВВЕДЕНИЕ

В этом уроке вы познакомитесь с ещё несколькими конструкциями Ogre и углубите материал предыдущего урока.

Этот урок в основном посвящён вопросам работы с источниками света (объекты Light) и созданию теней с их помощью.

Также в нём освещаются основные принципы работы камер (объекты Camera).

ДЛЯ НАЧАЛА

Как и в прошлой статье мы возьмем за основу уже готовый код.

К классу BaseTurtorial2 мы добавим два новых метода createViewport и createCamera.

Эти две функции уже определены в базовом классе BaseAplication, но в этом руководстве мы рассмотрим их поподробнее, чтобы увидеть, как в действительности создаются и используются объекты Camera и Viewport (область просмотра).

Добавим определение методов createCamera() и createViewports() в заголовочный файл нашего класса:

Затем добавим реализацию этих функций.

КАМЕРЫ

КАМЕРЫ OGRE

Камера (класса Camera) – это объект, который мы используем, чтобы увидеть созданную нами сцену.

Объект Camera, это специальный объект, работа которого похожа на работу объекта SceneNode

У объекта Camera есть функции установки позиции (setPosition), углов рысканья (yaw), крена (roll) и тангажа (pitch), вы также можете прикрепить его к любому узлу сцены.

Как и у объекта SceneNodes, позиция объекта Camera зависит от его предков (хорошо уважать старших %)

При любых перемещениях и поворотах вы можете рассматривать камеру как узел сцены.

Есть одно замечание о камерах Ogre, которое вы, вероятно, не ожидали: вы можете использовать только одну камеру в каждый момент времени (в текущей версии (<i>прим. пер:</i> 1.7 и ранее, в более поздних версиях может измениться)).

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

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

Эти узлы сцены просто находятся на сцене и указывают на точку, которую камера хотела бы обозреть.

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

Мы еще вернемся к этой методике в руководстве по FrameListener.

СОЗДАНИЕ КАМЕРЫ

Мы переопределим стандартный метод, который BaseApplication использует для создания камеры.

Найдите функцию-член BasicTutorial2::createCamera().

Первым нашим делом будет создание объекта Camera.

Поскольку камеры привязаны к менеджеру сцены, в котором они находятся, мы используем объект SceneManager для их создания.

Добавьте эту строку кода для создания камеры:

Она создает камеру с именем "PlayerCam".

Обратите внимание, что вы можете использовать функцию getCamera() менеджера сцены для получения камер по их имени, если вы решите не хранить указатель на них.

Следующим шагом будет установка позиции камеры и направления ее обзора.

Мы будем размещать объекты вокруг начала координат, так что поместим камеру на приличном расстоянии в направлении +z и заставим ее смотреть на начало координат.

Добавьте это код после предыдущего:

Функция lookAt довольно изящна.

Вы можете направить камеру на любую интересующую вас точку вместо указания углов поворота по осям (yaw, roll и pitch).

Объекты SceneNode также имеют эту функцию, которая может упростить настройку поворота объекта в большенстве случаев.

И наконец, мы установим расстояние до ближней плоскости отсечения равным 5 единиц.

Всё, что находится ближе ближней или дальше дальней плоскостей отсечения, мы не будем видеть.

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

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

Вы также можете установить расстояние до дальней плоскости отсечения.

Это убережет движок от отрисовки всего, что находится дальше этого значения.

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

Для установки расстояния до ближней плоскости отсечения добавте строку:

Установка дальней плоскости отсечения производится аналогично, вызовом setFarClipDistance (хотя вы не должны использовать дальнюю плоскость отсечения со стенсильными тенями, которые мы будем использовать в этом уроке).

Теперь, поскольку мы переопределили функцию createCamera(), нам нужно создать OgreBites::SdkCameraMan (контроллер камеры), используя нашу только что созданную камеру:

Функция createCamera теперь выглядит так:

ОБЛАСТИ ПРОСМОТРА (VIEWPORTS)

ОБЛАСТИ ПРОСМОТРА (VIEWPORTS) В OGRE

Когда вы начнете работать с несколькими камерами одновременно, класс Viewport станет для вас более полезным.

Мы затронули эту тему сейчас, потому что важно, чтобы вы понимали, как Ogre решает, какую камеру использовать при отрисовке сцены.

В Ogre возможно использовать несколько менеджеров сцены (SceneManager) одновременно.

Также возможно разделить экран на несколько областей, и использовать отдельный рендеринг для разных областей экрана(подумайте, к примеру, о раздельной игре 2 игроков в консольной игре).

Хотя это сделать и возможно, мы не будем рассматривать это до продвинутых уроков.

Чтобы понять, как Ogre отображает сцену, рассмотрим три конструкции Ogre: камеру (Camera), менеджер сцены (SceneManager) и окно отрисовки (RenderWindow).

Мы еще не сталкивались с окном отрисовки, но вкратце, это окно, где все отображается.

Объект SceneManager создает камеры для обзора сцены.

Вы должны указать в объекте RenderWindow, с каких камер выводить изображение на экран и в какой его части.

Область, в которую вы говорите окну отрисовки отображать камеру, и есть область просмотра.

В большинстве случаев использования Ogre, вы обычно создаете только одну камеру, регистрируете ее для использования всем окном отрисовки и поэтому имеете только один объект Viewport.

В этом уроке мы расскажем, как зарегистрировать камеру для создания области просмотра.

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

СОЗДАНИЕ ОБЛАСТИ ПРОСМОТРА

Мы переопределим создание области просмотра, производимое в BaseApplication, так что найдите функцию-член BasicTutorial2::createViewports().

Чтобы создать область просмотра, мы просто вызываем функцию addViewport класса RenderWindow, передавая ей используемую нами камеру.

В классе BaseApplication уже было заполнено поле mWindow нашим объектом RenderWindow, так что добавьте эту строку кода:

Теперь, когда мы имеем область просмотра, что мы можем сделать с ней? Ответ будет: не многое.

Самая важная вещь, которую мы можем сделать с ней, это вызвать функцию setBackgroundColour() для установки фона в любой выбранный нами цвет.

Поскольку мы работаем с освещением в этом уроке, мы установим черный:

Обратите внимание, что ColourValue ожидает красную, зеленую и синию компоненту цвета в диапазоне от 0 до 1.

Последняя и самая важная вещь, которую мы должны сделать, это установить соотношение сторон нашей камеры.

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

Мы пойдем дальше и установим его даже при том, что мы используем соотношение сторон по умолчанию:

Это все, что должно быть сделано при простом использовании нами класса Viewport.

Вот так выглядит законченная функция createViewports():

К этом моменту вы должны быть в состоянии скомпилировать и запустить приложение, хотя ничего, кроме пустой сцены, и не появиться (нажмите Escape для выхода).

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

СВЕТ И ТЕНИ

ТИПЫ ТЕНЕЙ, КОТОРЫЕ ПОДДЕРЖИВАЕТ OGRE

На данный момент OGRE поддерживает три типа теней:

Модулятивные текстурные тени(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE) - наименее вычислительно-затратная техника из трех. Она производит черно-белую отрисовку в текстуру объектов, отбрасывающих тени, и эта текстура затем применяется к сцене.

Модулятивные стенсильные тени (Ogre::SHADOWTYPE_STENCIL_MODULATIVE) - эта техника отрисовывает все теневые объемы как модуляцию (т.е. накладывание теней поверх уже освещенной сцены) после всех непрозрачных объектов, уже отрисованных на сцене. Тени не такие насыщенные, как с использованием аддитивных стенсильных теней, но при этом техника не столь точна.

Аддитивные стенсильные тени (Ogre::SHADOWTYPE_STENCIL_ADDITIVE) - эта техника отрисовывает каждый источник света как отдельный добавляющий проход по сцене (т.е., в отличие от предыдущей, сцена не затеняется тенями, а наоборот, освещается источниками света). Это очень нагружает графическую карту, поскольку каждый источник света требует дополнительного прохода при отрисовке сцены.

Ogre не поддерживает мягкие тени как часть движка.

Если вам нужны мягкие тени, вам нужно будет написать свои собственные вершинные и фрагментные шейдеры.

Обратите внимание, что здесь дается краткое введение &ndash; руководство по Ogre полностью описывает тени в Ogre и результаты их использования.

ИСПОЛЬЗОВАНИЕ ТЕНЕЙ В OGRE

Использовать тени в Ogre относительно просто.

Класс SceneManager имеет функцию-член setShadowTechnique(), которую мы можем использовать для установки желаемого типа теней.

Теперь, всякий раз при создании сущности, вызывайте функцию setCastShadows(), чтобы указать, должен ли объект отбрасывать тени.

Сейчас мы установим окружающее освещение в полную темноту и настроим тип теней.

Найдите функцию-член BasicTutorial2::createScene() и добавьте туда этот код:

Теперь менеджер сцены использует аддитивные стенсильные тени.

Давайте создадим объект на сцене и заставим его отбрасывать тени.

Также нам нужно что-нибудь, на чем мог бы стоять ниндзя (а также отбрасывать туда тени).

Этим что-то будет простая плоскость.

Мы не посвящали этот урок использованию менеджера сеток (MeshManager), но тем не менее пробежимся по самым основам, которые потребуются при создании плоскости.

Для начала нем необходимо определить сам объект плоскости, что делается заданием вектора нормали и расстоянием от начала координат.

Мы могли бы (к примеру) использовать плоскости для задания частей геометрии мира, в этом случае надо указать что-то отличное от 0 для расстояния.

Сейчас нам просто нужна плоскость с нормалью, направленной в положительном направлении оси y (что означает, что она смотрит вверх), проходящая через начало координат:

Теперь нам надо зарегистрировать плоскость, чтобы мы могли использовать ее в своем приложении.

Класс MeshManager отслеживает все загруженные нашим приложением сетки (например, следит за использованными нами сетками robot.mesh и ninja.mesh).

Функция-член createPlane() принимает определение плоскости и создает сетку на основе своих параметров.

Она регистрирует нашу плоскость для использования.

И снова, мы не будем глубоко вникать в специфические особенности того, как использовать MeshManager (обратитесь к соответствующему разделу API, если вам нужно увидеть, что в точности означает каждый параметр).

Мы просто создали плоскость размером 1500 на 1500 условных единиц и назвали получившуюся сетку "ground".

Теперь мы можем создать объект Entity из этой сетки и поместить его в сцену:

Замечательно, да? Однако, прежде чем мы закончим, мы должны сделать ещё две вещи с нашей землёй.

Во-первых, нужно сообщить менеджеру сцены, что мы не хотим, чтобы земля отбрасывала тень, поскольку она должна её принимать.

Во-вторых, мы должны наложить на неё текстуру.

Сетки робота и ниндзя уже имеют определенные для них материалы.

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

Мы будем использовать материал "Examples/Rockwall" который идет с примерами Ogre.

Вот так должна выглядеть наша функция createScene в данный момент:

Теперь, когда в сцене есть Ниндзя и земля, давайте скомпилируем и запустим программу.

И мы видим... ничего!

Что же произошло? В предыдущем уроке мы добавляли Роботов и они нормально отображались.

Причина, по которой Ниндзя не показывается, состоит в том, что окружающее освещение сцены установлено в полную темноту.

Так что давайте добавим источник света, чтобы видеть, что происходит.

ТИПЫ ИСТОЧНИКОВ СВЕТА

Ogre предоставляет три типа источников света.

Точечный (Ogre::Light::LT_POINT) - точечные источники света излучают свет во всех направлениях.

Прожектор (Ogre::Light::LT_SPOTLIGHT) - работает точно также, как прожектор. Вы задаёте позицию источника света и направление, в котором свет будет излучаться.

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

Directional (Ogre::Light::LT_DIRECTIONAL) - Направленный свет эмулирует далекий источник света такой как солнце или луна, так что он освещает все содержимое сцены под одним углом.

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

Один из способов добиться требуемого состоит в том, чтобы использовать направленное освещение и установить ему то направление, откуда приходит свет луны.

Источники света обладают обширным набором свойств, которые определяют, как выглядит данный источник. Два из них являются наиболее важными &ndash; это цвета рассеянного (diffuse) и бликового (specular) освещения. Каждый скрипт материала определяет, сколько рассеянного и бликового освещения отражает материал; управление данными свойствами мы изучим в одном из следующих уроков.

СОЗДАНИЕ ИСТОЧНИКОВ СВЕТА

Для создания источника света в Ogre мы вызываем метод createLight объекта SceneManager и передаём ему имя источника света &ndash; все очень похоже на то, как создаются объекты Entity или Camera.

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

В отличии от объекта Camera, источник света имеет только методы setPosition и setDirection (а не полный набор функций для перемещения, вроде translate, pitch, yaw, roll и т.д.).

Таким образом если вам необходимо создать стационарный источник света, воспользуйтесь функцей setPosition.

Если же вам нужно перемещать источник света (к примеру, создать источник света, следующий за персонажем), вы должны присоединить его к объекту SceneNode.

Итак, давайте начнем с самого основного источника света &ndash; точечного.

Первое, что мы сделаем – создадим источник света, установим его тип и позицию:

Теперь, когда мы создали источник света, мы можем установить его рассеянный и бликовый цвета освещения. Давайте сделаем его красным:

Теперь скомпилируйте и запустите приложение. О да!

Теперь мы можем видеть Ниндзя и он отбрасывает тень.

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

Заметьте также то, что вы не "видите" источник света.

Вы видите свет, который он испускает, но не сам объект-источник.

Во многих уроках по Ogre добавляется простая сущность на место источника света, чтобы показать, откуда он излучается.

Если вы испытываете трудности с освещением в вашем приложении, вам стоит рассмотреть вопрос создания чего-то подобного, чтобы точно видеть, где на самом деле находятся ваши источники света.

Теперь давайте попробуем направленный источник света. Заметили, что спереди ниндзя стал черным, как смола?

Давайте добавим небольшое количество желтого направленного света, который попадает на переднюю часть его тела.

Мы создаем источник света и устанавливаем его цвет точно также, как мы это делали для точечного источника света:

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

Мы установим направление излучаемого света положительным по оси z и отрицательным по оси y (чтобы он шел под углом 45 градусов спереди и повыше ниндзя):

Компилируйте и запускайте приложение.

Теперь у нас две тени на экране, хотя, поскольку направленное освещение слишком тусклое, тень тоже тусклая.

Последним типом источника света, с которым мы собираемся поиграть, является прожектор. Сейчас мы создадим синий прожектор:

Также мы должны установить как позицию, так и направление излучения источника света.

Мы создадим прожектор, висящий над правым плечом нашего Ниндзя и светящий вниз непосредственно на него.

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

Представьте себе на секунду луч света фонарика.

В центре выделяется основной луч, который ярче окружающего света.

Мы можем установить ширину обоих лучей, вызвав метод setSpotlightRange:

Скомпилируйте и запустите приложение. Фиолетовый Ниндзя... опасный чувак!

Функция createScene к этому моменту должна выглядеть так или как-то похоже:

ДОМАШНИЕ ЗАДАНИЯ

РАЗЛИЧНЫЕ ТИПЫ ТЕНЕЙ.

В этой демке мы используем только тип теней SHADOWTYPE_STENCIL_ADDITIVE.

Попробуйте применить два других типа теней и посмотрите, что получится.

Также в классе SceneManager существует множество функций, относящихся к теням.

Попробуйте поиграть с некоторыми из них и посмотрите, к чему это приведет.

ОСЛАБЛЕНИЕ СВЕТА

Источники света имеют функцию setAttenuation, которая позволяет управлять степенью рассеивания света по мере удаления от источника.

Добавьте вызов функции для точечного источника света, поустанавливайте различные значения ослабления. Как это повлияет на свет?

SceneManager::setAmbientLight

Поэкспериментируйте с функцией setAmbientLight менеджера сцены.

ЦВЕТ ФОНА ОБЛАСТИ ПРОСМОТРА

Измените значение ColourValue по умолчанию в функции createViewports.

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

Camera::setFarClipDistance

В методе createCamera мы устанавливаем растояние до ближней плоскости отсечения.

Добавьте вызов функции setFarClipDistance и установите расстояние до дальней плоскости отсечения в 500 единиц. Посмотрите, что получится, когда вы будете двигаться из положения, в котором вы видите Ниндзя, в положение, в котором вы его не видите с включенными стенсильными тенями. Заметили замедление?

Примечание: для того, что бы это работало и вы могли заметить эти странные тени, вы должны установить mSceneMgr->setShadowUseInfiniteFarPlane(false) (Смотрите эту ветку обсуждения).

ПЛОСКОСТИ

Мы не так много рассказали о плоскостях (объектах Plane) в этом уроке (на этом не было сконцентрировано наше внимание).

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

ЗАКЛЮЧЕНИЕ

Теперь вы должны иметь начальное представление о камере, источниках света и тенях.

Мы будем часто использовать их в следующих уроках.

Внимание! Этот перевод, возможно, ещё не готов.
Его статус: перевод редактируется

Переведено на Нотабеноиде
http://notabenoid.org/book/19615/64001

Переводчики: Mingun, wuffur, PoqXert, alexx_x

proVIDec

Настройки

Готово:

100.00% КП = 2.1