в общем случае
идёт линейная интерполяция вдоль :) ребра с меньшим разбиением
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 ( смотрит строго
> вниз и вниз перемещается ) работает ?
ну да, конечно : )
Тема в архиве.