среда, 16 февраля 2011 г.

quad engine 0.1.3
Закончен перевод базовых классов на интерфейсы. Создан заголовочный файл. Как только все работы по переводу будут завершены, quad можно будет использовать в любом языке программирования, поддерживающем интерфейсы. К сожалению, жертвой интерфейсам стала необходимость запечь весь quad в dll. Хотя, на текущий размер скромен — 280Кб. В масштабах современных разработок размер более чем скромный, не так ли?
К счастью, подход имеет больше плюсов, чем минусов. И еще один из таких плюсов — ООП подход.
На текущий момент реализованы 4 базовых интерфейса: IQuadRender, IQuadTexture, IQuadFont и IQuadShader. Боюсь, что до завершения переделки движка на интерфейсы, новостей не будет. Также надеюсь что переделка не займет много времени.

вторник, 8 февраля 2011 г.

Наконец-то дошли руки до модуля, создающего окошко и управляющего получением сообщений. Видимо туда же перекочует и таймер. Пока в зачаточном состоянии, однако уже результат налицо. Минимальное приложение рисующее прямоугольничек на черном фоне и создающее лог выглядит так:

program Project1;

uses
  Windows, QuadWindow, QuadRender, QuadLog;

var
  qr : TQuadRender;
  ql : TQuadLog;

procedure Main;
begin
  qr.BeginRender;
  qr.Clear(0);
  qr.Rectangle(0, 0, 10, 10, Random($FFFFFFFF));
  qr.EndRender;
end;

begin
  CreateWindow;

  ql := TQuadLog.Create;

  qr := TQuadRender.Create;
  qr.Initialize(h_Wnd, 640, 480, ql);

  OnIdle := Main;
  EnterMainCycle;
end.



Ехе файл при этом 60Кб. Вполне доволен результатом. Оу... забыл. Добавил дополнительные поля в лог при инициализации. Теперь движок "знает" о аспекте, количестве и разрешении мониторов в системе.

пятница, 4 февраля 2011 г.

Как ковалось железо, или "параллакс меппинг и использование изнутри".

В предыдущем посте я рассказал и показал пример parallax oclusssion mapping. Как это используется в реальности, что там происходит... Короче, для интересующихся расскажу как добиваюсь эффекта по шагам.

Шаг1:
В рендертаргет (в примере равный размеру окна) рендерится диффузная карта местности.

Шаг2:
В тот же рендертаргет через multiply рендерятся "тени" от объектов. Пока они плоские, также как и сама карта диффуза, но она исказится чуть позже.
Шаг3:
Во второй рендертаргет рендерится карта высот для всего ландшафта.
Шаг4:
В третий рендертаргет рендерится карта нормалей для всего ландшафта.
  
Шаг5:
Тут начинается все самое интересное. Сразу забыл оговориться, что три рендертаргета используемых в предыдущих шагах это три текстуры в трех разных стейтах и ипользуются они одновременно.
Эти три текстуры прогоняются через шейдер (о нём позже), который создает эффект "вдавливания" текстуры. Но так как в особо сильно вдавленных местах информация о текстуре заканчивается, мы получаем неприятные артефакты вокруг результата, в зависимости от степени вдавленности (в нашем случае максимальное вдавливание равно 128 пикселям). К сожалению, избавиться от эффекта невозможно, однако можно немножко считерить. 
Вариантов решения проблемы два. Первый — научить шейдер не вдавливать текстуру, а выдавливать. Второй — затекстурировать полигон так, чтобы текстурные координаты были не 0,0 - 1,1, а что-то вроде 0.1,0.1 - 0.9,0.9 или же просто увеличить полигон за пределы экрана в каждую сторону на 128 пикселей. Я избрал метод вдавливания так как при вдавленном методе не искажаются самые высокие участки, которые больше всего и видны игроку. Поэтому использовал второй метод решения проблемы.
Собственно что получится без коррекции  при попытки "вдавить":
 Когда текстурные координаты поправлены и артефактов нет, получаем то, что хотели, но чуточку побольше размером. А так как мы в диффузный рендертаргет нарисовали и тени — получаем еще и тени, причем с учетом искажения по рельефу:
Шаг 6:
Осталось дорисовать сами объекты поверх ландшафта, делая это привычным методом. Тут уже никаких секретов нет.

Шейдер:
Шейдер заслуживает отдельной статьи так как достаточно объемен. Сначала в программе высчитывается TBN для вершин (в quad-engine делается автоматом), далее TBN, матрица проекции и позиция источника света передаются в вершинный шейдер. Вершинный шейдер переводит все полученные параметры в тангент-спейс полигона и дальнейшая работа уже идет с ним. На выхлопе для каждого пикселя вектор света и вектор вида.
Пиксельный шейдер. Из карты высот берется значение высоты и учитывая вектор вида в данной точке ищется пересечение луча вида с плоскостью с учетом поправки на высоту (взятую из карты высот). Далее идет 8 итераций на корректировку текстурных координат, точнее на поиск более близкого значения к желаемому. После нахождения производится ленейная интерполяция в пределах 1\8 глубины (для этого и делается 8 проходов). Таким образом получается достаточно точное значение, которое и берется как реальные текстурные координаты. Пиксель из этих текстурных координат уже и выводится. Также по этим текстурным координатам берется вектор из карты нормалей и производится затенение картинки, согласно расположению источника света (в примере ровно по центру экрана). Добавляется спекуляр и эмбиент по вкусу и результат готов.

Подробно с кодом почитать о Parallax mapping можно вот здесь.

четверг, 3 февраля 2011 г.

Всем доброго вечера. Сегодня спешу представить сильно доработанную, но пока не финальную версию параллакс мэппинга в исполнении quad. 
Идея возникла следующая. Что, если фон состоит из тайлов ( в примере из 6 по 512х512 ) и они скроллируются? Должен возникнуть эффект параллакса. То что выше — двигается быстрее, то что ниже — медленнее. К тому же более высокие части ландшафта должны перекрывать более низкие при соотвествующих углах зрения. 
Более того, что если над этим ландшафтом летит самолёт и он должен отбрасывать честную тень на ландшафт с учетом изменения формы (высоты) ландшафта? Разумеется, тень должна "плыть" по ландшафту. Искажаться. Вуаля:
В данном демо источник света установлен ровно по центру экрана, а уровень спекуляра минимален для всей сцены (около 15%). Используется 3 карты — диффузная, нормали и карта высот. Рендеринг осуществляется в 4 прохода. Комбинирование всех диффузных карт (сюда же входит и "плывущий" логотип), комбинирование карт высот, комбинирование карт нормалей и финальный рендер с наложением шейдера.
Для гибкой настройки по скорости выполнения предусмотрена возможность менять размеры рердертаргета и получать прирост в скорости в до 4х раз при скромном размере рендертаргета. (в демонстрации размер рендертаргета соотвествует размеру окна).
Скачать пример (670Кб)