Neptune
> float height = HeightMapTerra(point);
> float сolor = ColorMapTerra(point, height);
а покажи эти функции )?
2Neptune
>Сфера поделена на изогнутые четырёхугольные куски, на каждом текстура и нормалмапа
А как ты делаешь синхронизацию между кусками по центрам лодов (ну где глаз висит) .. А в свое время делал 6 сторон куба оттрансформенные в сферу - у меня так и не получилось сделать совпадение центров лодов между всеми 6 гранями
Я про чтото типо такого - но тут тупо куб
я и на кубе не сделал
The Andreyp
Надо просто грани тоже в соседи (neighbor) прописать, а алгоритм quad-tree уже сам разрулит на автомате.
У меня 6 клипмапов. Не дерево!
Я слышал что камеру перводят в какое то простарнство и чета какието точки пересечения проектируют куда то хз
cNoNim
> а покажи эти функции )?
Пожалуйста:
float HeightMapTerra(float3 point) { float height = (fBm(point * surfParams.freq + Randomize) - surfParams.offset) * surfParams.norm; float montes = 3.0 * RidgedMultifractal(point * surfParams.freq * 117.3 + Randomize, 14, 2.7, 0.5, 0.7, 1.8); height += surfParams.montDistMagn * montes * saturate(10.0 * (height - surfParams.heightMont)); return saturate(height); } float4 ColorMapTerra(float3 point, float height, float slope) { float4 color; // Assign a climate type, roughly by latitude float climate; float latitude = abs(point.y); // Perturb climate zone with small noise noiseParams.NOctaves = 6.0; latitude += surfParams.colorDistMagn * fBm(point * surfParams.colorDistFreq + Randomize); latitude = saturate(latitude); if (latitude < surfParams.latTropic - tropicWidth) climate = lerp(surfParams.climateTropic, surfParams.climateEquator, (surfParams.latTropic - tropicWidth - latitude) / surfParams.latTropic); else if (latitude > surfParams.latTropic + tropicWidth) climate = lerp(surfParams.climateTropic, surfParams.climatePole, (latitude - surfParams.latTropic - tropicWidth) / (1.0 - surfParams.latTropic)); else climate = surfParams.climateTropic; if (height < surfParams.heightBeach) climate = 0.375; else climate = lerp(climate, surfParams.climatePole, pow((height - surfParams.heightSea) / (1.0 - surfParams.heightSea), 2.0)); if (height > surfParams.heightSea) { // Land //if (climate > 0.8) climate = 1.0; climate += 0.05 * fBm(point * surfParams.colorDistFreq * 73.7); color = tex2D(ColorTable, float2(climate, slope)); if (climate < 0.75) color.rgb += surfParams.colorDistMagn * DistfBm(point * surfParams.colorDistFreq * 100.0, 1.5); //color.rgb += 5.0 * surfParams.colorDistMagn * fBm(point * surfParams.colorDistFreq * 100.0); } else { // Oceans noiseParams.NOctaves = 2.0; float shelfZone = saturate((fBm(point * surfParams.freq * 0.47 + Randomize) - surfParams.offset) * surfParams.norm); float depth = 1.0 - 15.0 * (1.0 - height / surfParams.heightSea); color = tex2D(ColorTable, float2(0.2 * shelfZone * depth, slope)); color.rgb *= 1.0 + max(height - surfParams.heightSea, -0.5); color.a = 1.0; } // Ice caps if (latitude > surfParams.latIceCaps) color = tex2D(ColorTable, float2(1.0, slope)); return color; }
Функции типа fBm(), RidgedMultifractal() и т.д. описаны в книге Texturing & Modeling - A Procedural Approach.
Это пока очень примитивно и требует дальнейших экспериментов. Например горные массивы как-то нездорово кучкуются в центре материков (второй скрин). Надо вводить геологическое моделирование...
Нeптун - не мог ты ответить на мой вопрос. Наверняка сам делал клипмапами тоже
The Andreyp
> Наверняка сам делал клипмапами тоже
Quadtree, он уже раз десять объяснял. )
Опишу ландшафтный движок ещё раз.
Больше всего похоже на geo mipmap (chunked lod) на кубе. Берётся куб (точнее сфера, типа "надутого куба"), каждая грань - корень quad tree. Каждой грани соответствует большая текстура например 32768*32768 (текстура поверхности с водой в альфа-канале и 16-битная карта высот). В корене дерева - эта текстура, уменьшенная до размера например 512*512. Корень сплитится на 4 потомка, каждый из них тоже сплитится на 4 узла-потомка и так далее, если надо (это зависит от положения камеры и fov'а (угла зрения)). Первый уровень - 4 потомка корня - исходная текстура, уменьшенная до 1024*1024, и порезанная на тайлы 512*512 (4 штуки). Второй уровень - 2048*2048, - 16 узлов и 16 тайлов по 512*512, и так далее. 6 уровень - исходная детализация 32768*32768, 4096 тайлов. В принципе, максимальная детализация не ограничена. При рендере отпределяется, какие узлы видны, какие нужно сплитить на потомки, нужные текстуры грузятся в параллельном потоке (а при записи демки в потоке рендерера). Из тайла карты высот делается нормал мапа для освещения и меш с геометрией этого куска поверхности. Наиболее давно использованные текстуры и меши удаляются из памяти (LRU-кэш). Для процедурных планет всё то же самое, просто вместо загрузки текстуры с диска она генерируется специальным шейдером, описанным выше.
Меш имеет меньшее, чем текстура, разрешене (32*32), поэтому для самого детального лода текстур строятся ещё 4 уровня лодов мешей (32 * 2^4 = 512), использующих всё ту же текстуру. Поэтому в демке и на видео детализация геометрии и текстуры совпадают (на каждый пиксель по вершине). Разрешения текстур и меша могут быть другими (например у процедурных планет 256*256 и 32*32), алгоритму всё равно.
Критерий, по которому определяется, когда надо делить узел на потомки - это примерный размер его на экране. Если разрешение текстуры 512*512, а размер узла стал k пикселей, значит пора подгружать его потомки. Этот параметр k обычно равен 512, т.е. экранная детализация всегда примерно с пиксельной точностью (пока не достигнут максимальный уровень), но это приводит к чудовищному потреблению памяти... Если сделать k = 1024, памяти потребляется меньше, и планета загружается быстрее (меньше узлов), но становится немного размытой. В общем, этот момент ещё надо обдумать и переделать. Например ввести зависимость k от уровня лода. Ещё один момент - для рендера лода N нужно чтоб в памяти уже был лод N-1, т.к. пока текстуры лода N ещё грузятся, нужно что-то рендерить. В итоге в памяти всегда находится пирамида лодов для текущей позиции камеры. И наоборот, нельзя выгрузить 1 или 2 уровень, даже если камера летает у поверхности с лодами 10 уровня, иначе при быстром взлёте вверх рендерить-то будет нечего, придётся ждать, пока снова подгрузятся лоды 1 или 2 уровня.
Вот картинка (вместо текстур планеты - дефолтная, чтоб было понятно):
Подлетаем ближе - раз! ближняя "грань" - узел одного из 6 quad tree - разделилась на 4 дочерних узла. Подгрузились свои текстуры, создалась геометрия...
Подлетаем ещё ближе - теперь уже дочерние узлы делятся.
А вот несколько скринов подлёта к Марсу, справа в wireframe режиме
Проблема стыковки мешей решается как обычно - определяется лод соседа, и если он меньше на 1, берётся другой индексный буффер, в котором по этой стороне квадрата пропущена каждая вторая вершина. Данные о высоте в соседнем узле такие же, как в текущем, если они оба построены по одной и той же текстуре, а если по разным - тут я поступил хитро, при подготовке текстур включил по их периметру пиксели из соседних текстур (так что разрешение стало 514*514). Это заодно решило проблему бесшовной стыковки цветовых текстур при рендере (но не нормалмапов, для них надо брать по 2 дополнительных пикселя). Эта схема простая, но работает не очень хорошо. Например, трещины в ландшафте появляются, если лоды соседей отличаются больше, чем на 1 (это бывает при резких поворотах камеры), так же они всегда есть, хоть и малые, при переходах между текстурами разных уровней, ведь в этом случае пиксели по периметру всё равно разные (у текстуры другого лода их вообще в 2-4-8-... раз больше, чем у текущей). С процедурными планетами простое увеличение разрешения на 2 пикселя вообще не прокатывает. Короче, эту систему надо переделывать.
Правка от 06.03.2011: Пока что тупо добавил "юбки" по периметру патчей, щели пропали, но зато немного тормознее стало рендериться.
По поводу того, как производится тесселяция. Представьте куб, на каждой грани которого работает описанное выше quad tree. Для каждого узла дерева загружаются/генерируюся карта высот и цвета. По карте высот создаётся нормалмапа, и строится плоский меш меньшего, чем текстура, разрешения, вершины которого сдвинуты по вертикали на величину h из карты высот. Всё плоское. А теперь возьмём координаты вершины (x,y,h) и нормализуем её, опустив на сферу, а потом учтём высоту:
vec3 point = normalize(vec3(x, y, 1.0)) * (1.0 + h/planetRadius)
Другие грани куба получаются так же путём поворотов/отражений, или перестановкой компонентов вектора, если хотите.
The Andreyp
> Нeптун - не мог ты ответить на мой вопрос. Наверняка сам делал клипмапами тоже
У меня не клипмапы, да, а квад-три. Читай выше))
Neptune
> просто вместо загрузки текстуры с диска она генерируется специальным шейдером, описанным выше.
а ты не пробовал не использовать текстуру вообще, а генерировать высоту и цвет на лету, в вертексном и пиксельном шейдере соответственно?
Neptune
> Texturing & Modeling - A Procedural Approach
ухты годная книжка )))
cNoNim
> а ты не пробовал не использовать текстуру вообще, а генерировать высоту и цвет
> на лету, в вертексном и пиксельном шейдере соответственно?
Ага, по 10 мс на патч, 150 патчей в кадре - получается 1.5 секунды на кадр:)))
хм... а патч у тебя какой? и почему их так много?
Neptune
вот , Neptune - есть такой вопрос - тут две картинки - одна , та что поменьше - имеет почти такую же синюю планету , как и вторая - та что побольше - во всяком случае так воспринимается - хотя на маленькой картинке в реале в Игре текстура там намного ниже порядком , но так как картинка сжата то и детализация повысилась - так вот , если картинку сжать и вкинуть в GPU - а там обратно Zoom-ировать до того же размера - можно ли получить выше качество . И другое , если ты не будешь к примеру напрямую на экран выводить изображение ( которое ты генеришь ) , а увеличишь допустим виртуальную картинку раза в четыре - потом ужмешь до размеров экрана ( требуемого расширения ) и будешь выводить по столько картинок в секунду - по сколько тебе нужно ( к тому же если картинка еще не преобразовалась - можно заменить ее другой предыдущей - но уже со спецэффектом ) - плюс легче сделать анимацию для PR-ного ролика .
Нептун, а какой Лод системой отрисовываешь ландшафт ? Пи методом или другим ? И вообще какие бывают методы отрисовки ландшафта ?