Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Сделал мегатекстуры (4 стр)

Сделал мегатекстуры (4 стр)

Поделиться

Страницы: 1 2 3 4 5 6 Следующая

BishopПостоялецwww5 окт. 20172:59#45
0xc0de
> Технически можно, только смысла делать больше чем 64к х 64к я не вижу.
Смысла или возможности? Просто я про возможность написал. Смысла и я не вижу.

0xc0de
> Для мегатекстуры других не знаю.
На основе буфера записей с трассировкой этого буфера. Вообще там метод довольно хитрый, когда буфер хранит данные сразу всех "мегатекстур". Ещё на GF480 в 2560х1600 эта радость давала порядка 170 ФПС (с освещением, тонмапингом, но без теней) при мегатекстуре в DXT на ~48GB.

0xc0de
> Там речь шла о физическом кеше, а физический кеш находится в видеопамяти.
Хм... ну реально кеша то 2: видео память - L1, системная память - L2 и диск как основное хранилище. Ещё может быть вариант когда диск это L3, а основное хранилище в сети.

0xc0de
> Там советовали Zlib для мегатекстуры. Ты сам в другом предложении себе
> противоречишь, где говоришь, что мегатекстуры жмут не так.
Для мегатекстуры есть 2 основных разумных подхода. Либо на диске в DXT + быстрая реализация Huffman+LZ77 (это явно не zlib, но вполне реально иметь на одном ядре 256МБ/с). Либо свой аналог jpeg2000 (реально иметь 128МБ/с на одном ядре) + RAW в ОЗУ и видеопамяти. Идея с DXT сжатием на лету плохая. Пишу по резульатат своей работы на сабжем в 2011 году.

P.S. Если интересны детали схемы с трассировкой буфера - найди меня завтра вечером (часов в 11) в скайпе - я расскажу. Писать не буду ибо долго, а я устал :(

Правка: 5 окт. 2017 3:00

Джек АллигаторПостоялецwww17 окт. 201721:14#46
Продолжаю грузить текстуры.
После экспериментов выяснилось, что сразу писать в текстуру через glTexImage из другого треда, в то время как в основном она сэмплится - очевидно плохая идея.
Сейчас экспериментирую с PBO.
Ожидал получить отсутствие просадок фпс + асинхронную загрузку с диска.
Алгоритм следующий:
0. есть пул транспортных буферов - PBO. изначально они все помечаются как свободные буферы для подгрузочного треда. допустим, 8 буферов.
1. главный тред формирует запрос - какие тайлы мегатекстуры нужны
2. второй тред маппит запакованую мегатекстуру и пишет оттуда нужные куски в буферы. т.к. буферов ограниченное кол-во, то за раз пишется 8 тайлов, остальные тайлы ждут освобождения буферов.
3. главный тред получает сигнал что в таких-то буферах записаны такие-то тайлы. биндит буферы, биндит текстуры и заливает данные. буферы отмечаются освободившимися.
таким образом, за кадр может загрузиться не более восьми тайлов. притом, никаких синхронизаций с гпу до swap_buffers быть не должно. теоретически.
Реализация в точности по классическому туториалу http://www.songho.ca/opengl/gl_pbo.html, никакой отсебятины я не делал, за исключением выноса буферизации в отдельный поток.

И всё равно фпс просаживается. Результат конечно лучше - раньше вообще почти до нуля просаживалось, но это скорее из-за ограничения кол-ва загружаемых тайлов за кадр.
Притом, в туториале выше есть демка, где на гпу заливается гигабайт в секунду и никаких просадок нет.
В моем тесте сейчас dds тайлы, каждый по 64кб. Даже если грузить по одному тайлу за кадр, фпс просаживается примерно со 180 до 60 - в три раза. Это даже не близко не похоже на гигабайт в секунду.
Понятно, разница в 5-10мс погоды не играет и вообще просадки лучше не мерять так, но факт остается фактом - как-то я не так сделал подгрузку с PBO.

Может есть какие-то тонкости, на которые надо обратить внимание?

Правка: 18 окт. 2017 0:02

0xc0deПостоялецwww18 окт. 201718:02#47
Джек Аллигатор
Может дело не в загрузке, а в скорости обновления дерева мегатекстуры и indirection table?
Джек АллигаторПостоялецwww18 окт. 201721:30#48
Оказывается, всё дело в println.
Убрал их и просадок нет.

Тем не менее ты прав, скорость обновления всех структур мегатекстуры занимает серьезное время - 3-5мс. Не смотря на то, что это стабильная нагрузка, надо бы придумать как оптимизировать =\
У меня там цикл на 12 тыщ итераций, что избыточно на самом деле.

Джек АллигаторПостоялецwww21 окт. 201722:45#49
Натянул на планету, всё робит как и ожидалось.
Осталось дело за малым - написать генератор четырехканальной сжатой мегатекстуры.
Каналы:
x: высота
y: эмбиент
z: normal_x
w: normal_y

Но чего-то с распаковкой нормалей небольшая проблема.
normal_x и normal_y - это тупо x и y нормали без каких-либо преобразований из карты нормалей rgb по 8bit на каждый канал.
В шейдере:

vec2 d = texture(normal_map, te_map_texc).xy;
float nz = sqrt(max(1-dot(d.xy,d.xy),0.0));
vec3 n = vec3(d,nz);
И на первый взгляд кажется всё работает как надо:
+ без сжатия
+ восстановление z

но z всё же немного отличается от исходника.

Так и должно быть? Или я где-то накосячил и есть возможность восстановить компоненту z, близкую к исходной?

Demiurg-HGПостоялецwww22 окт. 20172:02#50
Джек Аллигатор
Для начала:
vec2 d = texture(normal_map, te_map_texc).xy * 2 - 1;    // <--------
float nz = sqrt(max(1-dot(d.xy,d.xy),0.0));
vec3 n = vec3(d,nz);
Джек АллигаторПостоялецwww22 окт. 20178:47#51
Demiurg-HG, а смысл?
normal_x и normal_y - это тупо x и y нормали без каких-либо преобразований из карты нормалей rgb по 8bit на каждый канал

получится вообще не то
+ Показать

у меня ведь значения изначально в [0,1]
если добавить запаковывание *0.5+0.5, а следом  *2-1, то результат почти неотличим от этого:
+ восстановление z

Видел статью http://aras-p.info/texts/CompactNormalStorage.html
Но там пакуют в half float. Вот интересно, можно ли без потери точности восстанавливать unsigned byte?
Пробовал разные методы оттуда - безрезультатно.
А вот первый метод отсюда http://www.gamedev.ru/code/forum/?id=121532 вроде как работает. О нём писал выше.

Джек АллигаторПостоялецwww22 окт. 20178:58#52
Хм, вроде понял где моя ошибка.
Нормали ведь должны быть в [-1,1]. Т.е. я изначально всё делаю не так.
Теперь понятно почему для нормалей берут точность half float - иначе будет пиксельное месиво.
Джек АллигаторПостоялецwww23 окт. 201722:26#53
Готово. Получил ровно то, что ожидал.
+ Показать

Главная цель достигнута - в видеопамяти вместо четырех 16к текстур размером более 300мб каждая получил 150мб фиксированный кэш для 32к мегатекстуры.
Карта покрытий имеет значительно меньшее разрешение, оттого разница в детализациях меша и текстур.
В будущем карта покрытий будет генериться по ходу игры и впечатление от картинки в целом изменится в лучшую сторону.

megatexture 7mips:
! размер куска 256x256
mip     x     y  ptx  pty  tiles
0    512   256    2    1      2
1   1024   512    4    2      8
2   2048  1024    8    4     32
3   4096  2048   16    8    128
4   8192  4096   32   16    512
5  16384  8192   64   32   2048
6  32768 16384  128   64   8192
                           10922

Всё это сжимается в DXT5 и пакуется в один непрерывный файл размером 715мб.
Изначально хотел 8 мипов и размер тайла 128х128, но по каким-то причинам вылетала ошибка переполнения стека. Где-то создавался слишком здоровенный массив под таблицу переадресации.
Было лень разбираться, всё равно в будущем переделаю всё это более оптимальным способом.
Потому размер тайла 256х256.

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

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

+ Показать

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

Правка: 23 окт. 2017 22:31

MisanthropeПостоялецwww24 окт. 20171:47#54
круть!
но повторять наверное не буду)
susagePПостоялецwww24 окт. 20172:01#55
Джек Аллигатор
> Как сделаю упреждающую подгрузку, быть может засниму ещё видос.
Для начало эта погрузка должна иметь ниже приоритет, относительно тех которые уже требуются.
Также приоритет для всех погрузок должно быть по уровню лода.

Если покрытие равномерно, в противном случае надо рассматривать с учетом масштаба.
1) Вычисляешь для каждой текстуры  min(lod) и max(lod)  и сравниваешь значения с предыдущего шага - вот и предсказание.
2) Зная скорость движения пикселя и камеры можно посчитать позицию для следующего фрейма,  взять dFx,dFy и вычислить  lod.
Для статике: предположим что мы всегда приближаемся, тогда можно составить формулу от( min(lod), max(lod), скорость движения)
lod это log от  dP.  Зная масштаб можно вычислить z, прибавить скорость. Обратно получить dP` взять log - получив предсказываемый lod`.

Джек АллигаторПостоялецwww24 окт. 20178:13#56
susageP, на самом деле всё куда проще.
В update мегатекстуры у меня цикл, итерирующий все тайлы и определяющий, насколько далеко находится данный тайл от камеры.
Это определяет lod. Оттуда составляется запрос в тред подгрузки.
Для опережающей подгрузки достаточно немного откорректировать формулу расчета, искусственно уменьшив расстояние до камеры.
А в другом цикле, что обновляет текстуру переадресации, выводить тайлы по старой формуле.
Я бы и сейчас сделал, но в планах оптимизировать update, так что оставил на потом.

> 2) Зная скорость движения пикселя и камеры можно посчитать позицию для
> следующего фрейма,  взять dFx,dFy и вычислить  lod.
lod рассчитывается перед рендером кадра на цпу. Т.е. все решения принимаются на цпу и я полностью контроллирую какие тайлы выводить.
dFx,dFy вообще не использовались.
Это позволяет читать из мегатекстуры в любом шейдере.
Возвращаясь на месяц назад:
0xc0de
> > Как тогда узнать высоту для вершины из карты высот в вершинном шейдере?
> Для террейна SVT не подходит. Только для текстурирования. Максимум -
> микрорельеф, который вычитывается из самого детального лода.
http://www.gamedev.ru/code/forum/?id=173761
таки нет ничего невозможного

vec4 read_megatex(in sampler2DArray tex, in sampler2D page_tex, in vec2 te_map_texc){
  vec2 page = texture(page_tex, te_map_texc).rg;

  float mip2 = exp2(page.g);
  float mip21 = exp2(page.g + 1);
  vec2 coord_low = fract(te_map_texc * vec2(mip21,mip2));

  return texture(tex, vec3(coord_low, page.r)).xyzw;
}

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

Правка: 24 окт. 2017 8:29

Fantom09Постоялецwww24 окт. 20179:56#57
В ядро ОГЛ 4.3/4.5 было добавлено пару расширений:

ARB_sparse_texture: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sparse_texture.txt
ARB_sparse_texture2: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sparse_texture2.txt
ARB_sparse_buffer: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_sparse_buffer.txt

Эти функции используются? В ссылках на первой странице я не нашел упоминания о них.

Джек АллигаторПостоялецwww24 окт. 201710:18#58
Fantom09, рад бы использовать, да железо их не поддерживает.
Но, если не ошибаюсь, эти расширения лишь упрощают работу с координатами и сэмплинг тайлов из кэша, а вся грязная работа по определению видимых тайлов и их подгрузке остаётся на программисте.
Так что сильно проще от их наличия не стало бы.

Вот что есть у меня:

+ Показать

innuendoПостоялецwww24 окт. 201710:57#59
Джек Аллигатор
> да железо их не поддерживает.

что-то какое-то древнее железо

Страницы: 1 2 3 4 5 6 Следующая

/ Форум / Программирование игр / Графика

Тема закрыта.

2001—2017 © GameDev.ru — Разработка игр