в общем случае
идёт линейная интерполяция вдоль :) ребра с меньшим разбиением
A0 * ( 1 - a ) + AN ( a )
где a от 0 до 1, с шагом 1 / ( N - 1 )
fanat
А какой порядка значения вершин ? ну x, y, z
я делал - проблем с точностью не было
innuendo
порядок здесь ни при чем.
Я там с масштабом перемудрил в свое время. Far плоскость в районе 100к.
А сетка 8*8к.
Вот и что там от float точности осталось.
Кстати, пробовал прямо сейчас уменьшит масштаб - артефакты почти исчезли.
Вообще истинное значение координаты (точное) и интерполированное - всегда немного различаются.
Если точночти вычислений не хватает - то пиксель выпадает(
бррр ещё раз и по-медленней!
чтобы устреднить высоту вершин, нужно физически их "подвинуть".. нужно лочить буферы это РАЗ.
далее для каждого лода нудно держать хренову тучу вершинных буферов? (буфер для каждого ЛОД-а + такой же но с усреднёнными высотами для соединения с чанком с более низким уровнем детализации) тогда например если ландшафт 1024*1024 , чанки размером 64 и 4 уровня детализации то:
это 256 чанков. Каждый чанк держит 4 вершинных буфера (ЛОД-ы) + все вариации этих ЛОД-ов с устреднёнными вершинами.. на каждый ЛОД таких вариаций:8 (например усреднено только сверху или снизу или угол сверху и справа)
тоесть воробщем в чанке 8*4 + 4 = 36 вершинных буферов! а на весь террайн состоит из 9216 вершинных буферов (страшно говорить про 4096*4096 террайн!!)
мож я просто чегото не понял.. мосх сегодня спит : )
я к тому, что... ну ЗАЧЕМэти шаманства? лочить буферы, менять вершины или держать туеву хучу маленьких буферов.
Можно ж просто индексный буфер так сформировать, то он будет "прореживать" нужную границу чанка в 2/4/8/16 и т.д. раз... (как это я себе сделал)
тупо ставим нужный индексный буфер и рисуем : )
я скрин не могу сделать, много чего в двиге переписываю. вот зарисовал
L
> чтобы устреднить высоту вершин, нужно физически их "подвинуть".. нужно лочить
> буферы это РАЗ.
обновляешь VB ( и не весь а только границы ) не каждый кадр ( реально lod сменяется раз в 5 - 10 в среднем )... и один буфер, текущий, хранится на GPU
L
> (как это я себе сделал)
А за сколько DIPS рисуешь chunk ?
fanat
> Если точночти вычислений не хватает - то пиксель выпадает(
не знаю, сколько я мудрил - ничего не выпадало :)
innuendo
> А за сколько DIPS рисуешь chunk ?
эмм.. за один о_О
innuendo
> обновляешь VB ( и не весь а только границы ) не каждый кадр ( реально lod
> сменяется раз в 5 - 10 в среднем )... и один буфер, текущий, хранится на GPU
это для ландшафта 1024*1024 будет 256 SetStreamSource??? ппц
L
> > А за сколько DIPS рисуешь chunk ?
> эмм.. за один о_О
тут что-то не то :)
L
> будет 256 SetStreamSource??? ппц
зачем ?
L
не чанк, а пачт ( лод ) - извини
за сколько лод рисуешь ?
в том примере , что я выложил, сетка 64к,а в все лоды содержат 9раз по 1024 вершины.
В кадре - не более половины (~40%).
Поэтому нет здесь вбо. Вершин совсем мало, вся нагрузка на филрейт)
innuendo
ну сколько видно, столько и рисую.
тоесть:
1. куллим ландшафт и далее работаем только с видимыми чанками!!
2. если камера (игрок) передвинулся на другой чанк (отличной от того, что был в предыдущем кадре) - у чанков меняем типы индексных буферов и LOD (тупо номер записываем)
3. выставляем вершинный фуфер (SetStreamSource)
4. группируем чанки по их типу (уровень детализации и т.д.)
5. для каждой группы чанков:
а. выставляем один раз индексный буфер этой группы
б. рисуем все чанки из этой группы (DrawIndexedPrimitive с оффсетом)
6. смотрим на ЪЪЪ картинку и радуемся высокому фпс и качеству ландшафта : )
L
> чанков меняем типы индексных буферов и LOD (тупо номер записываем)
а вот эти типы индексных буферов как считаешь, сколько там комбинаций ?
а случай, когда камера как бы падает строго по направлению Z ( смотрит строго вниз и вниз перемещается ) работает ?
итого 1 чанки ланшафта - 1 DIP ?
если кому интересно то вот моя функция - генерирует индексный буфер с LOD-ом и прореживает указанные стороны!
ох и намучался я с ней когдато.. нигде небыло исходников (даже теории не нашёл : ( ) пришлось исписать и исчетрить листов 15 принтерных гыг
private IndexBuffer GenerateLOD(int chunkLength, Device device, int lodNumber, bool trimTop, bool trimBottom, bool trimLeft, bool trimRight) { int mNum = 1, Counter = 0; switch (lodNumber) { case 1: mNum = 1; break; case 2: mNum = 2; break; case 3: mNum = 4; break; case 4: mNum = 8; break; } IndexBuffer _ib = new IndexBuffer(device, (chunkLength / mNum) * (chunkLength / mNum) * 6 * sizeof(int), Usage.WriteOnly, Pool.Default, false); int[] Indices = new int[(chunkLength / mNum) * (chunkLength / mNum) * 6]; for (int i = 0; i < chunkLength / mNum; i++) { for (int j = 0; j < chunkLength / mNum; j++) { Indices[Counter] = Convert.ToInt32((i + 1) * (TerrainWidth + 1) * mNum + j * mNum); Counter += 1; Indices[Counter] = Convert.ToInt32(i * (TerrainWidth + 1) * mNum + j * mNum); Counter += 1; Indices[Counter] = Convert.ToInt32(i * (TerrainWidth + 1) * mNum + (j + 1) * mNum); Counter += 1; Indices[Counter] = Convert.ToInt32((i + 1) * (TerrainWidth + 1) * mNum + j * mNum); Counter += 1; Indices[Counter] = Convert.ToInt32(i * (TerrainWidth + 1) * mNum + (j + 1) * mNum); Counter += 1; Indices[Counter] = Convert.ToInt32((i + 1) * (TerrainWidth + 1) * mNum + (j + 1) * mNum); Counter += 1; } } //-----------------LOD trimmers---------------------------- //trim top corner if (trimTop) { for (int i = 0; i < (chunkLength / mNum); i++) { if ((int)((float)((i + 1) / 2f)) == (float)((i + 1) / 2f)) { //чётная Indices[i * chunkLength / mNum * 6 + 0] = 0; Indices[i * chunkLength / mNum * 6 + 1] = 0; Indices[i * chunkLength / mNum * 6 + 2] = 0; } else { Indices[i * chunkLength / mNum * 6 + 3] = Indices[(i + 1) * chunkLength / mNum * 6 + 3]; if (trimLeft == true) { if (i != 0) Indices[i * chunkLength / mNum * 6 + 4] -= (short)(mNum); else Indices[i * chunkLength / mNum * 6 + 0] -= (short)(mNum); } else { Indices[i * chunkLength / mNum * 6 + 4] -= (short)(mNum); } Indices[i * chunkLength / mNum * 6 + 0] += (short)(mNum); } } } //trim bottom corner if (trimBottom) { for (int i = 0; i < (chunkLength / mNum); i++) { if ((int)((float)((i + 1) / 2f)) == (float)((i + 1) / 2f)) { //чётная Indices[(i + 1) * (chunkLength / mNum) * 6 - 6 + 0] = 0; Indices[(i + 1) * (chunkLength / mNum) * 6 - 6 + 1] = 0; Indices[(i + 1) * (chunkLength / mNum) * 6 - 6 + 2] = 0; Indices[(i + 1) * (chunkLength / mNum) * 6 - 6 + 4] -= (short)mNum; } else { Indices[(i + 1) * (chunkLength / mNum) * 6 - 6 + 5] = Indices[(i + 2) * (chunkLength / mNum) * 6 - 6 + 5]; } } } int offset = (chunkLength / mNum) * ((chunkLength / mNum) - 1) * 6; if (trimRight) { //Trim right corner for (int i = 1; i < (chunkLength / mNum) + 1; i++) { if ((int)((float)i / 2f) == (float)i / 2f) { //чётная Indices[offset + (i - 1) * 6 + 0] += (short)(mNum); Indices[offset + (i - 1) * 6 + 3] = 0; Indices[offset + (i - 1) * 6 + 4] = 0; Indices[offset + (i - 1) * 6 + 5] = 0; } else { Indices[offset + (i - 1) * 6 + 5] += (short)(mNum); } } } if (trimLeft) { //Trim left corner offset = (chunkLength / mNum) * 6; for (int i = 1; i < (chunkLength / mNum) + 1; i++) { if ((int)((float)i / 2f) == (float)i / 2f) { Indices[(i - 1) * 6 + 0] = 0; Indices[(i - 1) * 6 + 1] = 0; Indices[(i - 1) * 6 + 2] = 0; } else { Indices[(i - 1) * 6 + 0] += (short)(mNum); Indices[(i - 1) * 6 + 2] += (short)(mNum); Indices[(i - 1) * 6 + 4] -= (short)(mNum); } } } //_ib.SetData(Indices, 0, LockFlags.None); _ib.Lock(0, Indices.Length * sizeof(int), LockFlags.None).WriteRange<int>(Indices); _ib.Unlock(); return _ib; }
innuendo
> итого 1 чанки ланшафта - 1 DIP ?
так и естьinnuendo
> а вот эти типы индексных буферов как считаешь, сколько там комбинаций ?
на 1 LOD - 9 комбинаций! тоесть или нормальный или с прорежеными сторонами.
innuendo
> а случай, когда камера как бы падает строго по направлению Z ( смотрит строго
> вниз и вниз перемещается ) работает ?
ну да, конечно : )
Тема в архиве.