Игровой уровень. Моделирование, текстурирование и шейдеры, или Геймдев. Начало

Хочу начать с благодарности всем тем, кто голосовал за мой первый урок и очень надеюсь, что второй вам тоже понравится.
Данный урок поведает о принципах создания игрового уровня под лучший, из бесплатных графических движков OGRE с использованием 3DS MAX и VRay, и последующего текстурирования его при помощи шейдеров. Для начала предлагаю углубиться в теорию. Постройка геометрии уровней для игр требует использования минимального количества полигонов, что обусловлено скоростью современных компьютеров и видеокарт в частности. Но тут многое зависит от особенностей движка, самой игры, типа используемых теней. Поэтому я не буду заниматься оптимизацией геометрии, так как в каждом конкретном случае могут быть разные варианты.

Теперь о том для чего нам нужен VRay. В современных играх используется несколько способов освещения и создания теней. Это Лайтмап, вертексные и пиксельные шейдеры для освещения, а для создания теней тот же Лайтмап, стенсильные и текстурные методы. Каждый из них имеет свои достоинства и недостатки. Использование шейдеров для расчёта освещения, очень красивый и перспективный метод. Он основан на просчёте освещённости каждой точки в реальном времени и имеет неоспоримые преимущества при текстурировании движущихся объектов, но расплачиваться за красоты нам приходится сильным падением производительности, при повсеместном его использовании. Тут нам на помощь приходят Лайтмапы или карты освещённости, они представляют собой, в большинстве, монохромные текстуры с заранее просчитанным освещением. И VRay в этом деле отличный помощник. Но в силу того, что данный способ использует освещение просчитанное на стадии создания модели и не может динамически изменяться, мы не можем использовать его для текстурирования движущихся объектов.

Невозможность использовать лайтмапы для динамических объектов не подразумевает под собой их статичность. Прекрасный пример использования динамических карт освещения можно посмотреть в демке Арсена Гнаткивского aka Troglodit "Magic Of Stonehenge" которую можно найти здесь: http://www.ogre3d.h14.ru/stonehenge/
Игровой уровень со стенами домами и прочими недвижимыми частями прекрасно подходит для этого способа текстурирования.

OGRE - Object-Oriented Graphics Rendering Engine. Бесплатный графический движок для игр и других 3Д приложений. Официальный сайт проекта: www.ogre3d.org , сайт русскоязычного комьюнити www.ogre3d.org.ru .Так как использование самого движка подразумевает под собой хоть малейшее знание программирования, то использовать мы будем очень интересную разработку - oFusion, которую можно найти по адресу http://www.ofusiontechnologies.com/ . Эта утилита встраивает окно рендеринга Огра в один из Вьювпортов 3DS MAX. Что даёт возможность оценить как ваш уровень или модель будут выглядеть непосредственно в игре.

Я думаю, с теорией мы разобрались и можем приступать к практическим занятиям.
Делать мы будем помещение, схожее с теми, в которых мне приходилось работать. Хочу сразу оговорить, что я не претендую ни на самый правильный метод моделирования и не говорю, что мои настройки для рендера или шейдеры являются единственно правильными, просто метод моделирования который я буду описывать дальше является самым удобным для меня и даёт ровную сетку, в отличии от Булевских операций, например. Для удобства установите единицы измерения в метры(Customize->Units Setup->Metric и Meters из выпадающего списка.) Начнём с пола, для чего создадим квадрат размером 7 на 10 м и высотой 0.1м с сечениями 5х9.

Конвертнём его в Editable Poly (Правой кнопкой мыши на объекте, потом Convert to:-> Convert to Editable Poly) и передвинем вершины как показано на рисунке.

Теперь выделим полигоны по краю кроме одного с номером 1 и сделаем Extrude на 1м. Этим мы обозначим начало оконных проёмов, а пропуск на месте не выбранного полигона послужит дверью. После чего выделяем полигоны без образовавшихся над номерами 2, 3, 4 и снова Extrude, на 0.5м , и не изменяя выделения на 1м и ещё 0.5м. Чтоб стало более понятно, что мы должны получить, взгляните на нижеприведённый скриншот:

Сейчас нам надо удалить показанные на рисунке полигоны, перейти в режим редактирования Edge и при помощи инструмента Bridge привести это к окончательному виду. Вот пошаговая инструкция для тех, кто никогда не пользовался данным инструментом:

Можно подправить пропорции окон и двери на данном этапе. Например, я опустил чуть ниже верхнюю линию двери и нижнюю линию окон, переместив соответствующие вершины. Для стен и поля я собираюсь использовать три материала: пол, верхняя и нижняя часть стен. Чтобы это осуществить мы должны назначить этим частям геометрии разные Material ID. Выделяем все полигоны которые будут у нас полом и в разделе Polygon Properties устанавливаем Set ID:1. Нижней части стен назначим ID:2 и верхней ID:3.

С самими материалами мы разберёмся чуть позже, а сейчас давайте сделаем окна. Ничего мудрить тут не будем, так как помним об экономии полигонов, поэтому соберём простенькие рамы из Box примитивов и один большой Box вместо оконного стекла. Теперь конвертируйте это всё в Editable Poly и при помощи Attach соедините рамы в один объект. На дверь нам тоже не стоит слишком растрачивать полигоны. Если вы решите пофантазировать и продолжить пространство за дверью коридором, или ещё каким либо помещением, то можете сделать дверь со стеклом, а в данном случае у нас будет опять таки Box. Потолок делаем тоже одним большим боксом и для более интересного вида добавляем ему несколько деталей в виде поперечных балок, которые подопрём колоннами. Колонны представляют собой бокс с сечениями 1х4. Нижнее сечение выровняем по высоте с тем, которое мы сделали чуть выше нижней границы окон.

В итоге у нас должно получится 6 объектов: пол и стены, оконные рамы, стекло , дверь, потолок с балками, колонны. Пора заняться текстурированием. Открываем Материал Эдитор, называем первый материал Wall_Floor, нажимаем на кнопку Standard и выбираем Multi/Sub-Object Установим количество материалов в 3. Первый из них назовём Floor, второй Wall_Dn, третий Wall_Up. Назначим им текстуры, перетянем наш Wall_Floor материал на объект и отредактируем UV координаты так, чтоб это всё имело нормальный вид. Создайте по материалу на каждый из 6-и объектов нашей сцены. Мульти саб материал нужен ещё колоннам. Окнам, рамам, двери и потолку назначьте стандартные материалы. При редактировании текстурных координат обратите внимание на то, чтобы Map Channel в разделе Chanel, модификатора UVW Mapping был установлен в 1. После проведения этих операций моя сцена стала выглядеть вот так:

Пришло время V-Ray. Я использую версию 1.47. В более ранних версиях возможны проблемы с рендером в текстуру, так что если у вас возникнут какие либо непонятные артефакты с ранней версией, попробуйте его обновить. Как устанавливать освещение зависит от вас, никаких конкретных замечаний здесь нет, главное чтоб выглядело красиво :). Я поставил один Директ лайт как солнце и три V-Ray Plane Light на окнах, для общей подсветки помещения. Множитель у солнца установил в 1.1, у оконных "лампочек" по 12. Создадим чистый V-Ray материал и установим его в слот Override mtl: в свитке Global switches настроек рендера. Вот мои настройки тестового рендера, они дают хорошую скорость предварительного просчёта и относительно хорошую картинку:

Разрешение: 320х240
Image sampler: Fixed rate > Subdivs 1
Indirect illumination:
Primari bounces: Irradiance Map > Current preset > Very low
И галочку на Show calc. phase, чтобы видеть процесс рендеринга и возможно подправить параметры не дожидаясь окончания этого процесса.
Secondary bounces: Light cashe > Subdivs 300
И тоже галочка на Show calc. phase.

Можно также снять галочку с Show window в свитке Vray::System, что уберёт окошко лога выводимое при рендере, также скройте на время рендеринга оконное стекло, чтоб свет от солнца нормально попадал в помещение.
Поправляем параметры по вкусу и когда отрендеренная картинка вас устроит можно продолжать.

Открываем окно настроек рендера и в свитке VRay::Frame buffer ставим галочку на Enable built-in Frame Buffer и Save separate G-Buffer channels. Нажимаем Browse... и выбираем папочку, куда мы будем сохранять наши лайтмапы. Сразу указываем понятное название, чтоб не запутаться в последствии, например, Wall-FloorLM.tga Формат значения не имеет, я взял .tga чтоб иметь несжатый вариант, а в последствии из него всегда можно создать .jpg вариант меньшего объёма.
Переходим в свиток Vray::G-Buffer/Color mapping и в G-Buffer output channels выбираем Real RGB. Настройки рендера теперь можно закрыть.

Выделяем Wall_floor объект и нажимаем Rendering->Render to Texture... В свитке Objects to Bake должен находится наш Wall_floor объект. В General Settings устанавливаем путь всё к той же папке, где мы собираемся хранить наши лайтмапы. В Mapping Coordinates отмечаем Use Automatic Unwrap и ставим Channel 2. Это значит, что Макс автоматически просчитает для нас дополнительные текстурные координаты для лайтмапы и поместит их во 2-ой канал. Опускаемся ниже и нажимаем кнопку Add… в свитке Output и из появившегося списка выбираем LightingMap. Имя файла здесь значения не имеет, так как мы будем использовать сохранённый Vray-ем. Чуть ниже устанавливаем размер нашей лайтмапы. Для первого, тестового рендера размер ставим поменьше, например 256 (на выходе будет текстура 256х256 пикселей) И в Baked Material галочку на Render to Files Only. Если вы вдруг забудете установить эту галочку, то Макс добавит к имени материала назначенного данному объекту, после просчёта, слово "orig_". Тогда вам нужно будет удалить это дополнение и повторно перетянуть материал на объект. Теперь можно жать Render и смотреть результат. Макс развернёт нашу модель и просчитает текстуру по этой развёртке. Если всё нормально, и не возникло никаких проблем, то выставляем настройки качества рендеринга на более качественные и увеличиваем размер выходной текстуры до 1024, также не лишним будет увеличить параметр Subdivs в настройках лампочек, что даст нам менее зернистую картинку и если имеется много времени установите Global subdivs multiplier в Vray::QMC Sampler в 2. Опять Рендер и ждём окончательного результата. После этого в указанной вами папке вы найдёте файл Wall-FloorLM.RGB_Color.0000.tga который и будет тем, что нам нужно. Выглядеть у вас он должен примерно так:

Развёртка далеко не самая лучшая, но заставить Vray отрендерить лайтмап по созданным заранее текстурным координатам получается не всегда. Также стоит учитывать, что при подготовке развёртки для лайтмапы вручную, наложение текстурных координат допускать не стоит. Переименуем его в более вразумительное Wall-FloorLM.tga. У объекта появился новый модификатор Automatic Flatten UVs это и есть его развёртка. Конвертнём его в Mesh или Poly. Теперь выбираем другой объект указываем куда и с каким именем сохранять, и рендерим. Проводим эту операцию для всех моделей нашего уровня кроме стекла. После чего сохраняемся и оставим Макс на время. На этом мы закончили первую часть нашего урока.

Часть вторая.
Пишем шейдер.

Я не буду расписывать здесь все нюансы написания шейдеров, а ограничусь лишь конкретно нашим случаем. Для тех, кто не совсем представляет себе что это такое, я постараюсь дать небольшое пояснение:
Шейдер - это программа, которая выполняется графическим процессором и отвечает за расчёт позиции вершин модели на экране монитора и цветом всех выводимых точек. Они бывают Вертексными и Пиксельными или Фрагментными (что одно и то же).
Прошу не путать шейдеры с материалом объекта. Это хоть и близкие, но немного разные понятия. Материал может содержать в себе несколько разных шейдеров, а может обходиться и без них.
Давайте определимся, как должен работать наш шейдер.
Нам нужны5 текстур на 1 материал. Это:

Diffuse map.
Normal Bamp map
Environment map
LightMap
Specular map

Specular map представляет собой черно-белую текстуру, и это даёт нам возможность засунуть её как Альфа канал в Diffuse map. В качестве Environment map лучше использовать CubeMap в формате .dds. Наш шейдер должен взять Diffuse map и умножить её на LightMap, что даст нам затенение в тех местах где есть тень. После чего мы приплюсуем к этому отражение основанное на Normal Bamp и перемноженное на Specular, чтоб определить где наш материал отражает, а где нет.
Я вас не напугал ?
Всё не так сложно как кажется, продолжаем.
Если вас заинтересовала тема шейдеров и вас интересует весь процесс их создания, то можете прочесть мой урок посвящённый непосредственно написанию бамп шейдера, который находится здесь:
http://www.ua-racing.org.ua/content.php?article.1

А я приведу готовый код с небольшими пояснениями.

Вертексный шейдер:

//Входные параметры нашего шейдера
float4x4 WorldViewProj;
float4 ViewPosition;

struct VS_INPUT
{
float4 Position : POSITION0; //Позиция вершины.
float2 uv : TEXCOORD0; //Основные текстурные координаты.
float2 uv2 : TEXCOORD1; //Текстурные координаты лайтмапы.
float3 Tan : TEXCOORD2; //Тангент вектор.
float3 Norm : NORMAL; //Нормаль.

};

//Это мы передадим в пиксельный шейдер.
struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float3 Norm : TEXCOORD2;
float3 Tan : TEXCOORD3;
float3 Binor : TEXCOORD4;
float3 CamPos : TEXCOORD5;
float3 VertPos : TEXCOORD6;

};

VS_OUTPUT vs_main( VS_INPUT In )
{
VS_OUTPUT Out;

//Позиция вершины на экране:
Out.Position = mul( WorldViewProj, In.Position );

//Текстурные координаты передаём без изменения.
Out.uv = In.uv;
Out.uv2 = In.uv2;

//Нормализируем Нормаль и Тангент вектор, и вычислим Бинормаль.
Out.Norm = normalize(In.Norm);
Out.Tan = normalize(In.Tan);
Out.Binor = cross(Out.Tan,Out.Norm);

//И это нам пригодится в пиксельном шейдере.
Out.CamPos = ViewPosition;
Out.VertPos = In.Position.xyz;

return( Out );

}

Пиксельный шейдер:

//Принимаем входные параметры и наши текстуры.
float4x4 WorldMat;

uniform samplerCUBE Env;
uniform sampler2D BaseMap;
uniform sampler2D NormalMap;
uniform sampler2D LightMap;

//Принимаем то, что отдал вертексный шейдер.
float4 ps_main( float3 Pos : POSITION,
float2 uv : TEXCOORD0,
float2 uv2 : TEXCOORD1,
float3 Norm : TEXCOORD2,
float3 Tan : TEXCOORD3,
float3 Binor : TEXCOORD4,
float3 CamPos : TEXCOORD5,
float3 VertPos: TEXCOORD6) : COLOR0
{

//Извлекаем нормаль из Бамп текстуры и распаковываем её из диапазона (0)-(1) в (-1)-(1)
float3 BampVec = (tex2D(NormalMap,uv)-0.5)*2;

//Вычисляем направление из камеры к нашей точке.
float3 VDir = normalize(VertPos - CamPos);

//Создаём матрицы для перевода векторов в тангент спейс и обратно.
float3x3 TanMat = float3x3(Tan,Binor,Norm);
float3x3 TanWM = mul(TanMat,WorldMat);

//Переводим направление камеры в Тангент спейс.
float3 ViewDir = mul(TanMat,VDir);

//Отражаем вектор от нашего объекта и переводим его назад в мировые координаты.
float3 RefVec = mul(reflect(ViewDir,BampVec),TanWM);

//Получаем цвет отражения, основной цвет, и цвет из лайтмапы.
float4 EnvCol = texCUBE(Env,RefVec);
float4 DifCol = tex2D(BaseMap,uv);
float4 LightMap = tex2D(LightMap,uv2);

//Вычисляем альфу.
float Alpha = 1-DifCol.a;

//И финальный результат:
return DifCol*LightMap + pow(mul(EnvCol,Alpha),1.5);

}

В рабочей версии шейдера комментарии желательно удалить, во избежание возможных проблем с русскими буквами.
Сохраняем их как LessShdr_V.source(вертексный) и LessShdr_P.source(пиксельный).

Нам понадобится ещё один файл, который мы назовём LessShdr.program и запишем там:

fragment_program LessShdr_P hlsl
{
source LessShdr_P.source
target ps_2_0
entry_point ps_main
}
vertex_program LessShdr_V hlsl
{
source LessShdr_V.source
target vs_1_1
entry_point vs_main
}

Этот файл укажет движку на наши шейдеры. Также то, что они написаны на HLSL и версию, которую должна поддерживать видеокарта для их выполнения.
HLSL-это высокоуровневый язык шейдеров для DirectX приложений, компилирующийся во время выполнения. Если вы хотите использовать их и под OpenGL то их не сложно переделать в CG, который может компилироваться под оба API.
На этом мы можем считать завершенным второй этап.

Часть третья.
oFusion

Пришло время установить oFusion, если вы этого ещё не сделали. Небольшое замечание: если у вас уже установлен какой либо экспортер Огровских моделей или вы будете устанавливать его позже, то они могут конфликтовать с oFusion. Конфликт происходит в плагинах материалов этих экспортеров. Поэтому перед запуском 3DS MAX определитесь какой экспортер вам нужен в данный момент и если это oFusion, то переместите файл initOgreTools.ms из 3DS MAX folder\scripts\startup в какую либо другую папку, а если вам нужен Огровский экспортер, то oMaterial.dlt из 3DS MAX folder\plugins. Не удаляйте эти файлы, они вам ещё могут пригодиться. Также нам надо установить созданный нами шейдер, для чего мы скопируем файлы, полученные в предыдущей части нашего урока в: 3DS MAX folder\oFusion\Media\shaders. Если у вас старая версия oFusion, то путь будет выглядеть так: 3DS MAX folder\ogre_azathoth\Media\shaders. Запускаем 3Д МАКС. У нас появился новый пункт меню "oFusion". Я не буду подробно описывать все его подпункты, для этого с ним поставляется неплохая справка, но некоторые мы всё же рассмотрим по ходу работы. Для начала нам надо выбрать в чём мы будем работать: Direct X или OpenGL. Для этого выбираем oFusion->Viewport где в Render System: выбираем Direct X, так как наш шейдер написан на HLSL. И нажимаем кнопочку "Set as Default Settings" чтобы сохранить наши настройки. Открываем нашу сцену. Для начала нам надо сбросить XForm для всех обьектов нашей сцены, так как oFusion очень чувствителен к этому моменту, и может отображать некоторые обьекты не правильно. Делается это через вкладку Utilities

Выбираем объект, нажимаем кнопочку "Reset XForm", в низу появится rollout "Reset Transform" где нам надо нажать "Reset Selected", после чего конвертируем его в Едитабл Меш или Поли. Если после этой процедуры нормали объекта вывернулись на изнанку примените к нему модификатор "Normal" и снова конверт в Меш или Поли. Также, для моделей с которыми мы хотим использовать карту нормалей нужно указать просчёт тангент вектора и делается это с выбранным объектом через oFusio->Object, где установите галочку на Generate tangent vector.

Теперь уберите из сцены все источники света, и установите только один Омни как солнце. В нашем случае это, в принципе, не обязательная часть, так как наше освещение уже просчитано и на источники света никак реагировать не будет, но возможно вы захотите добавить какие либо дополнительные объекты в помещение, которые должны будут отбрасывать реалтаймовую тень или иметь спекуляр или бамп составляющую. Сейчас нам надо перевести наши материалы в понятные oFusion-у. Он конечно понимает и стандартные материалы макса (Дифьюс карту, прозрачность), но чтобы раскрыть его возможности по полной программе используйте его материалы. Открываем Material Editor, выбираем какой либо материал из созданных нами ранее, например Floor, и нажимаем кнопочку Standard, в верху с права, возле имени материала. Из открывшегося списка выбираем oFusion Material жмём ОК после чего выбираем Keep old material as sub-material из появившегося диалога и снова ОК. Наш материал теперь находится в Max viewport/render material. Эта часть отвечает за то, как материал будет отображаться во вьювпорте Макса и при рендере. Тут у нас есть два пути для дальнейшей работы. Мы можем нажать кнопку Evaluate и материал создастся автоматически, а можем проделать эту операцию в ручную. Я советую второй способ, так как он поможет вам больше понять устройство огровских материалов, также материалы созданные при помощи Evaluate иногда могут отображаться не правильно.

Итак, мы видим надпись Techniques, под которой находятся четыре кнопочки с надписью None. Техники в Огре могут использоваться разными способами: для создания LOD материала, или как варианты материала для разных компьютеров. Например, первая техника с использованием шейдеров версии 3, вторая для видеокарт с первыми шейдерами, а третья для видеокарт не поддерживающих их совсем. Огр автоматически выберет нужную исходя из возможностей видеокарты начиная с первой.

Жмём самую верхнюю кнопку None и выбираем oFusion Technique. На этом уровне мы имеем место для четырёх проходов (Passes). Опять жмём верхний None и выбираем oFusion Pass. Перед нами открываются все параметры настройки прохода Огра и снова четыре места, для использования текстурных карт (Texture Units) и под ними интерфейс для назначения вертексных и пиксельных шейдеров, но он не будет работать пока мы не включим вьювпорт oFusion-а. И снова верхний None, и oFusion TextureUnit из списка. Тут мы опять видим кучу разных параметров, но не надо пугаться, разобраться во всём этом гораздо проще, чем может показаться на первый взгляд. Нам же, сейчас нужно установить нашу текстуру и делается это, как не сложно догадаться, при помощи кнопки с сопровождающей надписью Bitmap: . Жмём уже порядком поднадоевший None и выбираем карту отражения. Напомню, что для отражения удобнее использовать кубмап в формате .dds. Можете выбрать подготовленный мной, довольно нейтральный, подходящий в большинстве случаев, или какой либо скайбокс на ваше усмотрение. А можно создать кубмап нашей комнаты, и использовать его. После выбора, мы должны сообщить движку, что это именно кубмап, а не простая 2Д текстура, для чего установим "cubic" справа от той кнопочки, которую мы только что использовали и немного ниже, в "Addres Mode:" установите "clamp".

Большинство параметров настройки Texture Units при использовании шейдеров никакого значения иметь не будут, так как всё это можно регулировать непосредственно в шейдере, а вот параметры прохода очень и очень важны. Но в силу того, что их описание займёт слишком много места, сил и времени, и в данном случае их значение не играет большой роли, описывать здесь я их не буду. Да и в хелпе к Огру все они довольно подробно описаны. Итак, поднимемся на один уровень в верх, обратно к настройкам прохода, и выберем теперь второй Texture Units, в котором мы должны установить нашу дифьюс текстуру. Никаких параметров здесь менять не надо. Все используемые мной в этом уроке текстуры вы можете найти в прилагающемся к уроку архиве, но можете использовать и свои. Опять поднимаемся наверх, и в третий Texture Units ставим бамп карту. Ну и на конец в четвёртый установите Лайтмап, в данном случае Wall-FloorLM.tga. Назначить шейдер мы не можем, пока не будет активно окно oFusion-а. Повторите эту процедуру для всех объектов нашей сцены, назначив им их материалы и лайтмапы. Хотя вы можете сделать это и позже, если вам не терпится увидеть результат.

Пришло время включить oFusion. В окне перспективного просмотра, в левом верхнем углу, на надписи "Perspective" нажимаем правой кнопкой мыши и выбираем Views->Extended->oFusion Viewport, после чего мы должны увидеть логотип oFusion в этом окне. Его можно развернуть или использовать вместе с окнами изометрической проекции. Выделять объекты в этом окне не получится, тут придется воспользоваться стандартными вьювпортами Макса. Управление обзором при активном окне oFusion-а возможно несколькими способами. При выборе инструмента "Select Object"(стрелочки для выбора обьектов) и использовании стрелок на клавиатуре управление схоже с таковым в шутерах. Также можно поворачиваться вокруг объектов, перемещаться в экранной плоскости или использовать лупу из стандартных средств управления 3DS MAX. Если вы закрыли Material Editor, то откройте его снова, и перейдите в настройки прохода, где мы устанавливали наши Texture Units.Под ними вы видите два роллаута: Vertex Shader (Program) и Pixel Shader (Program). В обоих выпадающих списках выберите наши шейдеры. Если вы придерживались моих рекомендаций, то это будут: LessShdr_V и LessShdr_P для вертексного и пиксельного шейдеров соответственно. Теперь поставьте галочки на обеих Active.

Если вы увидели сообщение, значит, где-то в коде шейдера допущена ошибка. В таком случае уберите галочки и пересмотрите код. Если никаких сообщений нет, то продолжим. Нажмите кнопку "Edit" вертексного шейдера, где вы увидите интерфейс передачи параметров. Ставим галочку возле View Position и из выпадающего списка выберите "CAMERA_POSITION_OBJECT_SPACE". Также галочку возле WorldViewProj и "WORLDVIEWPROJ_MATRIX" из списка.

Теперь закройте это окно и откройте аналогичное для пиксельного шейдера где для WorldMat поставьте "WORLD_MATRIX". Если вы всё делали правильно, то вы должны увидеть наш пол, освещённый светом из окон и с блеском. Полетайте и посмотрите на результат, надеюсь после стольких трудов он вас обрадует :) Повторите эти действия для всех материалов, и мы займёмся последней деталью - стеклом. Для него тоже можно написать шейдер с разными красивостями, но мы тут воспользуемся стандартными материалами. Если вы не создали материал для стекла ранее, то сделайте это сейчас и назначьте на объект. Проводить эту процедуру лучше с отключенным вьювпортом oFusion-а, так как изменения геометрии и назначение материалов не отображаются в нём без его перезагрузки. В меню oFusion есть кнопки Update разных категорий, но они не всегда действуют, и лучше перезапустить окно после каких либо изменений. Нам нужен материал с одним Texture Units в который установите карту sph.jpg и в его настройках установите Env Map: на spherical, а в настройках прохода снимите галочку с Lighting, чтоб наше стекло не реагировало на внешнее освещение. В Src Blend: и Dst Blend: установите "one". Этим мы говорим что смешивать текстуру нашего окна с окружением надо сложением их цветов. В принципе поэкспериментируйте с этими параметрами, возможно вам больше понравится другой вариант.

Осталось установить небо за окном. Для этого откройте oFusion->Scene и в разделе Sky под надписью Type: поставьте SkyBox. То что получилось у меня после всех этих процедур, вы можете лицезреть на нижеприведённых скриншотах. Или у меня на сайте немного изменённая и обросшая деталями сцена: frees-st.narod.ru/games.html

Вот в принципе и всё. Мы с вами разобрали основные параметры oFusion-а, научились применять и шейдеры и стали ближе к геймдеву :)
Данную сцену теперь можно экспортировать из Макса и загружать в Огр. Но эта процедура подразумевает под собой некое количество программирования, что немного выходит за рамки данного урока. Если тема вас заинтересует, то в ближайшее время мы продолжим знакомство с такой интересной и увлекательной "игростроительной" стороной 3д.



Файлы урока: Files.zip (3 Mb)



С уважением
Пидвирный Андрей aka FreeS

www.frees-st.narod.ru
frees_les@mail.ru

667 0 850 38
25
2006-11-01
Большое спасибо за урок!!! Именно то, что мне сейчас нужно...
2006-11-02
Молодец автор... очень интересно))
2006-11-02
Рулез, прямо в точку, актуально и злободневно. Хочу еще Геймдева. Автору РЕСПЕКТ.
2006-11-02
Очень приятно читать такие отзывы. Спасибо.
2006-11-03
для 2000 года - прекрасная статья. Но теперь пора бы уж и повзрослеть. 1. "Постройка геометрии уровней для игр требует использования минимального количества полигонов, что обусловлено скоростью современных компьютеров и видеокарт в частности" - если вы не используете шейдеры или используете в шейдере модель освещения типа ambient (хотя зачем тогда такой шейдер???), то да. Если же используется хотя бы phong модель освещения, в которой вычисляется dot product для каждого пикселя, то все упирается в площадь поверхности геометрии, а не в количество полигонов. 2. Лайтмапы... как много в этом слове. Не надо забывать, что помимо невозможности динамически менять освещение лайтмапы делают и еще одну пакость.. Полностью убивают Next Gen. То есть все карты нормалей и спекуляры, которые вы нарисовали (надеюсь, вы знаете, что это такое), работать не будут на уровне, освещенном лайтмапами. Почему??? Потому что для их работы требуется вычислять формулу Фонга, например. А в этой формуле фигурирует вектор из точки до источника освещения. А источники освещения мы благополучно запекли в лайтмап, потеряв всякую информацию об их местоположении. 3. Автор какие-то отражения приплел.. Типа, эти отражения считаются по Normal Bump и Specular. И еще спрашивает: "я вас не напугал?" Напугал. Я отражений этих не вижу :-( 4. Почитал шейдер (не много думал). Я так и знал, никакими отражениями и правильными рассчетами нормалей и спекуляров (по положению источника освещения) там и не пахнет. =) и пару слов про OGRE. он даже из бесплатных не самый лучший. Лучший - это понятие субъективное, поэтому оставим этот вопрос на суд публики =)
2006-11-03
Может будет полезно и интересно, вот ссылка на небольшой рассказ про освещение по формуле Фонга http://en.wikipedia.org/wiki/Phong_reflection_model Это, конечно, не идеальная модель освещения, но она намного лучше лайтмапов вот там как раз и говорится про блики, нормали и все такое.. И про использование в формуле вектора из точки поверхности на источник освещения :-) на вскидку нашел только на английском. Но думаю, гугл вам поможет с переводом
2006-11-03
Для начинающих всё равно полезно будет, но про NextGen тоже не стоит забывать )))
2006-11-03
ну.. к раннее сказанному добавлю, что скачанный мной oFusion(7мб!) не поставился ни на 5 ни на 6 ни на 7 макс, так чтобы заработал, всегда его работа сопровождалась еррорами макс-скрипта.... Да и жаль что про шейдеры мало и только для dx.. "Игровой уровень со стенами домами и прочими недвижимыми частями прекрасно подходит для этого способа текстурирования." - насчет light map мне кажется что проше уж тогда из макса запекать прямо с готовым освещением... но это все, конечно лишь личное мнение )
2006-11-03
To Aed: Складывается такое впечатление, что ты слабо представляеш о чём говориш и о чём статья. А теперь по порядку. 1. Количество геометрии и полигонов играет большую роль. Всегда. Или это реалтайм или сцена под рендер в Максе. Не зависимо от системы освещения 1000 полигонов будут медленнее 10. И такие елементарные вещи надо знать, перед тем, как постить комментарии. 2. HalfLife2, FlatOut2 и много много других игр используют лайтмапы. По твоему там работают глупые люди? Позицию источника света мы не теряем. Источник экспортируется вместе со сценой, и можно сколько угодно использовать его позицию, цвет, и всё что угодно. 3. Если ты внимательно посмотриш на скриншоты, ты их увидиш. 4. То, что "(не много думал)" когда читал шейдер, это видно :) О спекуляре от источника света никто и не говорил. А отражением там как раз и пахнет :). И по поводу Огра. Первое место среди Open Source движков больше года. Этого мало? http://www.devmaster.net/engines/ To crol: То что у тебя он не заработал, это странно. Прекрасно работает и на 7, и на 8 Максе. Может поставил плохо?
2006-11-03
1. делаем 10-полигональный квадратик. Чтоб на экране был размером примерно 500 на 500 точек. Накладываем на него шейдерное освещение с расчетом карт нормалей, parallax occlusion mapping и моделью Oren-Nayar. Ну так, чтоб уж наверняка. Делаем такой же квадратик (по размерам), но с 1000 полигонами. Кладем на него шейдерное освещение по фонгу. Рендерим в любом двигле, которое поддерживает все фичи для первого 10-полигонального квадратика. Удивляемся (в Вашем случае) или подтверждаем логические выводы (в нашем). И больше не затрагиваем эту тему. 2. насчет HalfLife2 спорить не буду. Любой желающий может найти в нете информацию по этому поводу. А ваши выводы оставим на вашей совести. По поводу потери источников освещения... Не заметил в вашем шейдере, чтобы использования данных о позиции источника 3. на вашей статической картинке блики заметить сложно. Но если там они и есть, то точно рассчитываются не по классическим формулам (опять-же, смотрим шейдер). Отсюда сомнение в их правильности. 4. отражение от Cubemap - конечно хорошо.. Но имхо дешевая и сейчас редкоприменяемая вещь. Сплошной фейк.
2006-11-03
1. Как раз затрагиваем. Конечно в твоём примере 10 полигонов выдадут меньший ФПС, за щёт сложного для прощёта шейдера.. Но ты положи на них одинаковый материал, и посмотри что быстрее. 2. Этот шейдер и не использует источники. Для того там и лайтмап. 3. Ответ выплывает из предыдущего. Имеем отражение кубмапа, а не реальных источников. 4. Да, фейк. Как и большинство эфектов в играх. Тот же HalfLife2 и FlatOut2 используют его по полной программе. И никто не жалуется.
2006-11-03
03.11.2006 14:45:58, Aleksei Shutov 1. разница будет незначительной. Скажем так, на современной видеокарте вроде GeForce 7900 GTX этой разницы не будет заметно вообще. Даже если использовать, например, NVPerfHood. Гораздо важнее именно площадь поверхности, выводимой на экран (не видимой на экране, а именно выводимой), поэтому мы уделяем большое внимание оптимизации построения уровня. Конечно, если взять, скажем, персонажа в 2-3 миллиона полигонов и того же персонажа, но в low-poly варианте с картами нормалей, то разница будет очевидна. Но надо быть весьма глупым человеком, чтобы пытаться в realtime рендерить на видяхе модель из 2-3 миллиона полигонов. Гораздо существенней, например, спор о применении того же parallax maping'а. Если с помощью этой технологии делаютсякакие-либо дырки/провалы в стенах, которые можно сделать с использованием дополнительных 100-500 полигонов, то лучше использовать полигоны, чем parallax mapping. Не буду я вас учить делать игры. Каждый вправе идти по тому пути, который считает правильным. Скажу только, что ваш пример не то чтобы устарел.. Он просто не позволяет в полной мере использовать преимущества NextGen технологий. Которые, кстати, сейчас настолько распространены, что их уже можно считать "CurrentGen."
2006-11-03
Тут дело в том, что мы хотим получить, и для какой игры это делается. Для шутера эта технология, может, уже и устаревает (хотя до появления игр на полностью открытом пространстве с полностью честным освещением ещё надо подождать) но использовать бамп, паралакс и д.р. для автосимулятора, например, дело совсем не оправданное.
2006-11-04
Ей, народ! Если глосуете в минус, то хоть обьясните что не понравилось.
2006-11-08
Вот решил привести список некоторых игр, которые используют Лайтмапы, и отражения на статичных кубмапах. 1. HalfLife2 (lightmap,cubemap) 2. FlatOut2 (lightmap,cubemap) 3. F.E.A.R. (cubemap) 4. CallofDuty2 (lightmap) 5. SeriousSam2 (lightmap,cubemap) 6. DOOM3 (cubemap) Этот список можно продолжать очень долго. Эти игры тяжело назвать устаревшими в плане графики. Так, что о не актуальности данной технологии говорить ещё рано.
2006-11-11
тогда такой вопрос, а в какой из этих игр используется OGRE?) я думал уже давно используются динамические кубмапы...
2006-11-11
Чё за глупый вопрос? Причём тут Огр к этим играм? ********** А динамические кубмапы конечно используются, Need for Speed, например.
2006-12-04
Очень хороший урок. Надеюсь на продолжение! Для тех, кто говорит, что "материал устарел, кто так делает" и т.д. А покажите какой-нибудь свой урок по тому как что либо делать "профессионально" с Вашей точки зрения. Вместо того чтобы оценить конкретный урок Вы пишите, что это все "отстой". Но где же ваши работы? Конечно, вероятно, Вы работаете в какой-нибудь офигенной конторе по гейм деву? Только что-то я пока не видел ни одной достойной отечественной игры, чтобы она была "вся такая правильная". Точно так же наша компания никогда не постит свои работы, т.к. реальной оценки всеравно не получит. Люди смотрят и говорят, "кто так делает" и приводит в пример свою картиночку, которую он рендерил двое суток и моделил полтора месяца. Так каждый даун может с учебником макса и банкой пива. А вот когда надо сделать так, чтобы VRay рендерил меньше часа хорошую картинку с 50-80млн. полигонов в кадре и сам объект где-нибудь под 500 гектар, то я бы на них посмотрел. Так же и здесь: Привели !один из примеров! создания модели для Гам. И вместо того чтобы оценить работу ее заклевали. В общем респект тебе, Андрей! Надеюсь на продолжение банкета. Остальным - удачи в работе! P.S. Все ниже перечисленное - IMHO и песнь о наболевшем. Если захочется развить тему - удачи, на ПМ все равно не отвечаю :)
2006-12-04
[img]http://www.ofusiontechnologies.com/files/viewports.png[/img] за такую картинку в позиционировании продукта можно и в бубен словить )))) Макс поддерживает DX шейдера во вьюпорте. И все постэффекты и шейдэрные материалы можно навертеть и без офужанофф всяких. Может просто офужан качественнее соптимизирован и не тормозит? Ну с настройкой шейдеров там поудобнее наверное тож ))) Ну это так, к слову.... ))) [img]http://img357.imageshack.us/img357/3136/qqqqkw9.jpg[/img]
2006-12-04
... и еще. Фужн не позволяет работать в своем окне с мешем. Анимацию не показывает нифига аццкий рендар))) соответственно Animation - > Make Preview тож не пашет ... Вьюпорты макса все это кажут и все работает....
2006-12-04
...а не.. всетаки некоторую показывает, правда окно надо сбрасывать на стандартное и потом опять в офужн. . . o_O
2006-12-04
2 TribeWolf Большое спасибо! 2 [] RomB [] Тут дело не в шейдерах как таких, а в том, что это неплохой инструмент для людей желающих заняться геймдевом. На мой взгляд (и не только мой :) )Огр лучший из безплатных граф. движков. И оФьюжен предназначен именно для него. Шейдеры он отображает не в стандартном Максовском вьювпорте, а в окне рендеринга Огра, встраиваемого им во вьювпорт. На данный момент это лучший экспортер-редактор для Огра. Он конечно не идеален, но если лень писать свой, то лучше не найти.
2006-12-28
работа проделана огромная ....достои хороших оценок
2007-01-24
Урок обалденый! Пиши больше.
2007-07-18
Урок хороший и полезный. Единственное НО, никогда не стоит говорить что такая-то программа или такой-то движок лучший. Я сам не моделлер, программист, знаю Ogre уже несколько лет, но не считаю его лучшим из лучших. И операться на devmaster тоже не советую. Как посмотрел, так там в большинстве новички, которые толком-то и программировать не умеют, а хотят научиться и увидели всякие красивости на сайте разработчиков Ogre. Поначалу мне тоже понравилось, но когда докапался до внутренностей движка, был расстроен, очень. И вот уже несколько лет использую в проектах движок Irrlicht. Но сам урок ценный! Молодец. 10/10.
RENDER.RU