среда, 3 октября 2012 г.

Двухсторонняя карта смещения.

Сейчас пишу игру на конкурс шутеров на gamedev.ru. В игре планирую использовать несколько интересных техник и по мере реализации буду писать о них здесь.
Первая техника - двухсторонняя карта смещения (dual-sided dismplacement map) используется для создания разрушаемых стен, полов и других аналогичных поверхностей (далее для простоты буду называть такие поверхности стенами).


Описание техники.
У себя я использую текстуру формата RG8_SNORM - это позволяет хранить значения в диапазоне -1..1. Каждая стена представлена плоскостью, проходящей вдоль ее оси, эта плоскость рисуется два раза с разной нормалью к поверхности и разными каналами текстуры. Например, при первом проходе используется нормаль (1,0,0) и R-канал текстуры, а при втором - нормаль (-1,0,0) и G-канал, в шейдере позиция вершины смещается в направлении нормали к поверхности на половину толщины стены умноженную на значение из карты смещения:
vec2    offset  = texelFetch( unDisplacementMap, texcoord, 0 ).rg;
gl_Position     = position + vec4(unNormal * offset[channel & 1] * fHalfDepth, 0.0);

В случае, когда происходит пересечение смещенных полигонов их необходимо отсекать, для этого в evaluation шейдере идет проверка:
vec2    offset   = texelFetch( unDisplacementMap, texcoord, 0 ).rg;
bool    is_empty = (offset[0] + offset[1]) <= 0.0;
Результат передается в геометрический шейдер и если для всех трех вершин треугольника значение равно true, то этот треугольник отсекается.
Пример того, как это выглядит на рисунке:
Черная линия посередине - плоскость стены, зеленым и синим цветом показаны RG каналы карты смещений, серым цветом - отсекаемые области.


Реализация.
Для экономии памяти я использую виртуальное текстурирование. Для этого все стены разбиваются на квадраты размером 1 метр, в вершинах записывается координата текстуры и ее размер. Размер текстуры соответствует уровню тесселяции для квадрата.



Оптимизация.
Из-за неравномерной тесселяции сильно падает производительность, поэтому для оптимизации лучше разбить их на группы по уровню тесселяции.

2 комментария: