Шрифт:
Интервал:
Закладка:
Для расчета освещенности я сделал отдельную утилиту Rad. Как следует из сокращенного названия, она рассчитывала также и отраженный свет по алгоритму Radiosity.
Radiosity — это алгоритм расчета освещения, учитывающий отраженный свет. Посмотрите на картинку, на ней комната с синим полом, красным потолком и белыми стенами. На белых стенах появятся красный и синий оттенки.
В Radiosity нет точечных источников света, здесь каждая точка поверхности излучает энергию (свет). Каждая точка поверхности посылает свою энергию всем остальным видимым ей точкам. Часть энергии они поглощают, а часть — отражают. И так бесконечное число раз.
В программных реализациях Radiosity имеют дело не с бесконечным количеством точек, а с конечным количеством маленьких частей поверхности — патчей. Cамый простой алгоритм построения Radiosity: последовательно для кажого патча передавать его энергию всем видимым для него патчам. Тут сразу же возникает проблема в определении видимости одного патча из другого. Придется делать трассировку луча и искать пересечение этого луча со всеми остальными объектами сцены, что очень дорого по вычислениям!
Я поступил несколько иначе. Что если смотреть из центра патча по нормали к поверхности? Мы увидим все то, что видит патч, иначе говоря, мы видим другие патчи, излучающие энергию. Складывая вместе энергию этих патчей, мы можем посчитать количество энергии и света из сцены, достигающей наш патч. Назовем это количество входящим светом (incident light).
В Radiosity нет различия между источниками света и патчами (частями поверхности), а в реальном мире некоторые поверхности излучают свет. Значит, некоторые патчи должны уметь не только поглощать и отражать свет, но и излучать его. Свойство патча, отвечающее за его способность излучать свет, назовем emission. Как раз эмиссию патчей и задавал редактор.
Свойство патча, характеризующее его видимость, это количество излучаемой им в сумме энергии — исходящий свет (excident light).
incident = сумма всего света, который видит патч
excident = (incident * reflectance) + emission
Тогда для расчета освещения нужно выполнить эти две операции для всех патчей в сцене заданное число раз.
Основная проблема, которую предстояло решить, — визуализация сцены из центра каждого патча. Причем обзор должен охватывать полностью то полупространство, в которое направлена нормаль поверхности. Можно взять полусферу и установить на патч так, чтобы центр полусферы совпадал с центром патча, и спроецировать сцену на полусферу. Но ни одна графическая библиотека не позволяет это сделать.
Вместо полусферы используют полукуб (hemicube). Каждая грань куба — перспективная проекция с углом обзора 90 градусов.
Такой алгоритм очень хорошо оптимизируется с помощью железа — графического ускорителя. Нужно визуализировать лицевую грань куба и половинки левой, правой, верхней, нижней частей, соответственно поворачивая камеру. А поскольку в цвете мы ограничены значением от 0 до 1 (0–255), то вместо реальных цветов патчей мы будем использовать указатели на патчи — будем кодировать указатель из четырех байт в четыре компоненты цвета — RGBA. Тогда при рендеринге нужно отключить любое фильтрование, мы же не хотим интерполировать указатели.
Нужно учесть искажения объектов перспективой по краям. Пиксели на поверхности полукуба домножаются на косинус угла между направлением камеры и отрезком, соединяющим центр проекции с пикселем. Также нужно учесть закон косинуса: освещенность поверхности пропорциональна косинусу угла между нормали к поверхности и направлением на источник света.
Карта 1
Поскольку рассчитывать эти величины каждый раз для каждого патча слишком дорого, то разумней подготовить специальную карту, на которую мы будем домножать наш полукуб — multiplier map. Это и делает утилита Rad. При ее запуске параметром задается, сколько проходов (число отражений света) мы рассчитываем. Пересчет карты 2 (квартира) в восемь проходов на Riva TNT Vanta занимал примерно 6–8 часов. Но оно того стоило.
Ко второй версии я добавил зеркала и полупрозрачные поверхности.
Карта 2
Текстура — растровое изображение, накладываемое на поверхность полигональной модели для придания ей цвета, окраски или иллюзии рельефа.
Копланарные многоугольники — многоугольники, лежащие в одной плоскости.
Работа - Адамант
На третьем курсе университета я совсем забросил учебу и целый день сидел за компьютером, занимаясь то поисковиком, то 3D-движком. Я пытался собрать единомышленников на форуме GameDev.ru для написания своей собственной игры. У меня была надежда, что ее кто-нибудь заметит и даст начальные инвестиции на более серьезную разработку.
Я переехал из соседнего блока к одногрупнику Вале, через которого я выходил в общажную сеть. Мы полгода жили в трешке вдвоем до новогодней сессии.
На этом же курсе было разделение по кафедрам. Я выбрал кафедру ядерной физики. Перед новым годом я подарил пятизвездочный коньяк «Арарат» заведующему кафедрой. Коньяк не был дорогой, но этот жест очень понравился заведующему. Он сказал, что, в случае каких-либо проблем, я могу обращаться к нему лично.
В конце первого семестра я твердо решил, что пора бы найти работу. Где я мог заработать? Например, разгружая что-то. Я нашел заманчивое предложение в газете о разгрузке мешков с мукой. Физическая форма у меня была хорошая. Я поехал по объявлению в Питер. Там мужики мне объяснили, что в среднем за день нужно разгрузить несколько тонн муки. Если я согласен — меня ждут завтра к 8 утра. Хорошо, что ж, попробую.
На следующий день уже в 6 утра я был на железнодорожной станции. Только вот электричка не доехала до станции «Университет» — сломалась и парализовала все движение. «Значит, не судьба. Видимо, эта работа не для меня», — с икренним облегчением подумал я. И пошел просматривать предложения о работе программистом на популярном тогда сайте job.ru.
Резюме у меня было скромное: студент, знания С/С++, WinAPI, OpenGL, опыта работы нет, для себя программирую такой-то 3D-движок.
Мне ответило несколько компаний. Одна из них — «Адамант Мультимедиа». Это была компания, занимающаяся разработкой 3D Action игр и принадлежащая крупному строительному холдингу «Адамант». Офис «Мультимедиа» располагался практически в центре Питера на Сенной площади. Туда я и поехал на собеседование. Меня встретил технический директор Дамир и провел в «большую программерскую» на четвертом этаже. По периметру кабинета стояло семь столов. На каждом столе по два монитора, под столом — один-два блока компьютеров. Кто-то усердно смотрел в мониторы, кто-то что-то