DirectX Большая плоскость Тесселяция

Просто вопрос о тесселяции DirectX11.

В шейдере корпуса максимальный фактор тесселяции, который можно установить, равен 64 (не уверен, почему). Теперь, хотя этого достаточно для маленьких самолетов, когда речь идет о больших самолетах, этого просто недостаточно, и поэтому мне было интересно, как я могу визуализировать большие самолеты?

Следующий код генерирует мой квад R это радиус:

vertices[0] = D3DXVECTOR3(-R, 0.0f,  R); //Top left
vertices[1] = D3DXVECTOR3( R, 0.0f,  R); //Top right
vertices[2] = D3DXVECTOR3( R, 0.0f, -R); //Bottom right
vertices[3] = D3DXVECTOR3(-R, 0.0f, -R); //Bottom left
vertices[4] = D3DXVECTOR3(-R, 0.0f,  R); //Top left
vertices[5] = D3DXVECTOR3( R, 0.0f, -R); //Bottom right

indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 3;
indices[4] = 4;
indices[5] = 5;

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

vector<D3DXVECTOR3> verts;
vector<D3DXVECTOR2> tex;

float R = 1000;

for(int z = 0; z < 4; z++)
{
for(int x = 0; x < 4; x++)
{
float xOffset = x * (2*R);
float zOffset = z * (2*R);

// Load the vertex array with data.
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f,  R+ zOffset) ); //Top left
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f,  R+ zOffset) ); //Top right
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom right
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom left
verts.push_back( D3DXVECTOR3(-R+ xOffset, 0.0f,  R+ zOffset) ); //Top left
verts.push_back( D3DXVECTOR3( R+ xOffset, 0.0f, -R+ zOffset) ); //Bottom right

tex.push_back( D3DXVECTOR2(0.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(0.0f, 1.0f) );
tex.push_back( D3DXVECTOR2(0.0f, 1.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 0.0f) );
tex.push_back( D3DXVECTOR2(1.0f, 1.0f) );
}
}

// Set the number of vertices in the vertex array.
m_vertexCount = verts.size();

// Set the number of indices in the index array.
m_indexCount = verts.size();

// Create the vertex array.
vertices = new VertexType[m_vertexCount];
if(!vertices)
{
return false;
}

// Create the index array.
indices = new unsigned long[m_indexCount];
if(!indices)
{
return false;
}

for(int i = 0; i < m_vertexCount; i++)
{
vertices[i].position = verts[i];
vertices[i].texture =  tex[i];
indices[i] = i;
}

Вот как это выглядит при рендеринге зацикленной плоскости:

Как получается, что при использовании нескольких четырехугольников он не работает правильно?
Должен ли я решить эту проблему, создав цикл в моем классе графики, где я затем перевожу и рендерирую один и тот же квадрат снова и снова, чтобы создать сетку?

Надеюсь, это имеет смысл.

2

Решение

Весьма сомнительно, что вы действительно хотите тесселяции всей плоскости — вы просто тратите время на тесселяцию всей вещи, когда зритель не может даже определить разницу для удаленных точек. Рассмотреть возможность реализации своего рода в режиме реального времени уровень детализации (LOD) алгоритм. Концепция LOD состоит в том, чтобы предоставить больше деталей для более близких объектов, оставляя удаленные объекты проще, чтобы сэкономить время рендеринга. Вот изображение, которое вам поможет, если вы не «получите» LOD:

Изображение, иллюстрирующее LOD

High tessellation <-------------------------------> Low tessellation

Хотя эти конкретные модели были созданы вручную в программном обеспечении для моделирования, таком как Maya, в отличие от тесселяции на GPU в режиме реального времени, мы надеемся, что вы все еще понимаете. Когда камера находится далеко от модели, визуализируйте кролика справа, а когда он приближается, визуализируйте более детальных кроликов, пока камера не окажется рядом с объектом, когда вы будете рендерить его в полной красоте.

В свое время я обнаружил два метода LOD в реальном времени, которые я считаю превосходящими все остальные. Первый был разработан для рендеринга воды, и ссылка на него Вот — Я действительно не могу объяснить это намного лучше, чем они. Смотрите в изумлении (или указывайте и смейтесь, если я потерплю неудачу), как я сейчас пытаюсь объяснить другой!


  • Источник: первая запись в книге GPU Pro 4, Вольфганг Энгель
  • Ваше размещенное изображение может напоминать плохо перекошенный рельеф, если вы немного щурились. Так как это было разработано для местности, это, вероятно, было бы легче реализовать, чем другой метод, который был разработан для рендеринга воды.

Как известно любому хорошо осведомленному программисту, работающему на GPU, CPU работает быстрее, а GPU быстрее. Основным узким местом сложной графики является передача данных между процессором и графическим процессором. Занимает навсегда.

Этот метод, разработанный специально для рендеринга местности, представляет собой алгоритм, почти полностью основанный на графическом процессоре, предназначенный для создания подразделенной сетки с LOD на основе расстояния. Хотя производительность в значительной степени зависит от способности установленного оборудования поддерживать ее, этот метод сильно оптимизирован для скорости.

Практически, метод многократно подразделяет, пока не достигнет желаемого LOD — представленного некоторыми параметрами, передаваемыми программистом. Кроме того, выборка также выполняется на каждой итерации алгоритма, избегая большого количества ненужной обработки или разделения областей за пределами просмотр усеченного конуса.

Поскольку все данные, используемые этим методом, сохраняются и уточняются на графическом процессоре, центральный процессор остается в основном доступным для выполнения других задач. Кроме того, мы также используем гладкую схему перехода LOD, чтобы показать практическое применение алгоритма подразделения. Конечный результат (это изображение с частично наложенным каркасом) действительно классный:

Окончательный вывод

Теперь я не собираюсь лгать. Алгоритм сложно проглотить. Итак, я сделаю все возможное, чтобы раздеть это для вас. Вот язык:

Viewable region Видимая область, обозначаемая переменной R, определяется как выровненный по оси (обычно обращенный вверх) четырехугольник, который представляет область, которая должна быть подразделена и / или визуализирована. Эта область определяется центральной позицией и шириной, вытянутой в положительном и отрицательном направлениях вдоль каждой оси (см. Изображение ниже). Центральное положение обозначено RC. Применяемое смещение обозначается как Rλ. Граничные точки области обозначены P1, P2, P3 и P4. Изобразите видимую область региона следующим образом:

Видимый диапазон региона

Viewable region span Диапазон видимой области, обозначенный как θ, может быть количественно определен с помощью следующей функции, заданной точки P и примененного смещения λ:

θ (P, λ) = | PScreenR — ПScreenL|

пScreenL = (PVProjLxy)/ПProjLw

пScreenR = (PProjRxy)/ПProjRw

пProjL = PWL × matProjection

пProjR = PWR × matProjection

пWL = (PWx — λ, PВайоминг)

пWR = (PWx + λ, PВайоминг)

пW = P × matWorldView

Диапазон видимой области — это ширина области просмотра на экране.

Maximum viewable region span Максимальный диапазон видимой области, обозначенный как
θМаксимум, максимально допустимый диапазон видимой области. Это значение, которое задается пользователем, является одним из основных факторов в алгоритме LOD, а также играет ключевую роль в алгоритме подразделения. В алгоритме LOD, если любая заданная видимая область имеет диапазон видимых областей, больший, чем θМаксимум, он разделен на 4 новых видимых региона.

Relative quadrant code Этот код идентифицирует относительную позицию разделенной видимой области относительно ее родительской видимой области. Этот код рассчитывается в алгоритме подразделения и используется алгоритмом перехода LOD. Обычно кодируется как 2-битная маска, этот код становится частью определения видимой области.


Алгоритм имеет три основных этапа.

обзор

Шаг 1 (Подготовка): «Инициализация» + «Промежуточный буфер региона»

  • Просто настройка; Я не буду стирать руки, объясняя это.

Шаг 2 (Алгоритм подразделения): цикл, включающий «Удалять регион» и «Конечный буфер области»

Шаг 3 (Алгоритм LOD): «Конечный буфер области» + «LOD» + «Вывод»


Этап 2 — Алгоритм подразделения

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

Два выходных потока используются в геометрическом шейдере. Промежуточный выходной поток используется для хранения видимых областей, которые предназначены для дальнейшей обработки. Конечный выходной поток используется для хранения видимых областей, которые не требуют дальнейшей обработки в следующей итерации и должны отображаться как часть этапа 3 алгоритма. В геометрическом шейдере обрабатывается каждая видимая область и выполняется одно из следующих трех действий:

  1. Если видимая область определяется как не пересекающаяся с видом
    усеченный, он утилизируется. Выбранная видимая область не добавляется ни в промежуточный, ни в конечный поток вывода. Обязательно учитывайте смещения на этапе 3 алгоритма при определении того, пересекается ли видимая область или нет.

  2. Если диапазон θ видимой области, записанный как θ (RC, Rλ), больше, чем максимальный диапазон θmax видимой области, то видимая область R разделяется на четыре квадранта (R1, R2, R3, R4). Квадранты, каждый из которых сам становится видимой областью, затем добавляются к промежуточному выходному потоку для повторной обработки на следующей итерации цикла. Их относительный код квадранта (уникальный для каждого квадранта) также добавляется в выходной поток для идентификации относительного расположения разделенных видимых областей к их родительской видимой области. Этот код позже используется алгоритмом перехода LOD при рендеринге каждой видимой области. Чтобы разделить видимую область R, создайте четыре новые видимые области (R1, R2, R3, R4) с их соответствующими центральными позициями (R1С,R2С,R3С,R4С) и примененные смещения (R1λ,R2λ,R3λ,R4λ) определяется так:

R1С = (RCx — .5 × Rλ, рCy + .5 × Rλ)

R2С = (RCx + .5 × Rλ /, рCy + .5 × Rλ)

R3С = (RCx + .5 × Rλ, рCy — .5 × Rλ)

R4С = (RCx — .5 × Rλ, рCy — .5 × Rλ)

R1λ = .5 × Rλ

R2λ = .5 × Rλ

R3λ = .5 × Rλ

R4λ = .5 × Rλ

  1. Если видимая область охватывает θ (RСλ), меньше чем
    или равный максимальному диапазону видимой области θmax, тогда видимая область R добавляется в конечный выходной поток видимых областей.

Также обратите внимание, что на последней итерации цикла все видимые регионы должны быть добавлены в выходной поток на этапе 2.


Этап 3 — Алгоритм перехода LOD

На этапе 3 алгоритма визуализируется поток видимых областей. Необходимость этапа 3: заданная видимая область R с примененным смещением Rλ может быть смежным с другой видимой областью с примененным смещением, которое или вдвое или вдвое больше размераλ. Без выполнения плавного перехода между двумя видимыми областями разного размера при рендеринге могут быть видимые неоднородности или другие визуальные аномалии.

Чтобы избежать трещин в нашей тесселяции, каждая видимая область визуализируется путем разбиения видимой области на четыре четырехугольника, обозначенных Q1, Q2, Q3 и Q4. Граничные точки для каждого четырехугольника, состоящие из набора статических граничных точек (P1, п2, п3, п4) и изменяющиеся граничные точки (PL, пT, пр, пВ, пС), определяются следующим образом:

Граничные точки

В совокупности эти непересекающиеся четырехугольники будут покрывать одну и ту же поверхность
область как видимый регион, из которого они созданы. Граничные точки каждого
Четырехугольники рассчитываются для выравнивания с граничными точками соседних видимых областей четырехугольников. Морфинг четырехугольных граничных точек (PL, пT, пр, пВ, пС) рассчитываются так:

Морфинг граничных точек

Учитывая видимую область θ области в точке P и примененное смещение λ, записанное как θ (P, λ), используйте следующую формулу для вычисления коэффициента морфинга — записанного как T (P, λ):

Фактор морфинга

Мы рассчитываем каждый из общих факторов морфинга (TL, TT, Tр, TВ, TС) для просмотра
область R с центральной позицией RС и применяется смещение Rλ как так:

Общие морфинговые факторы


Проблема в том, что эти общие коэффициенты морфинга работают только тогда, когда соседние видимые области имеют такое же примененное смещение, как Rλ. См. Ниже: схема различных позиций, используемых при расчете общих коэффициентов морфинга.

Есть два особых граничных случая, которые мы должны учитывать при расчете
морфинговые факторы. Эти особые случаи возникают, когда одна видимая область является смежной с другой видимой областью с большим или меньшим примененным смещением λ. Случаи определены так:

Особые случаи

Особый пограничный случай 1

Видимая область R с примененным смещением Rλ находится рядом с
меньшая видимая область с примененным смещением .5Rλ.
Мы условно установим следующие морфинговые факторы следующим образом:

Особый пограничный случай 1

Приведенный выше набор условных тестов для случаев, когда смежный видимый
область была разделена на меньшие видимые области. Поэтому нам нужно
привязать затронутые морфинговые факторы к 1. Это сделано для того, чтобы все
перекрывающиеся четырехугольные вершины точно совпадают с вершинами меньших
смежный видимый регион. На изображении ниже представлена ​​схема различных
позиции, используемые при расчете коэффициентов морфинга для граничного случая 1.

Положения для пограничного случая 1

Граничный случай 2

Видимая область с примененным смещением Rλ смежна с большей видимой областью с примененным смещением 2Rλ. Чтобы иметь возможность выполнить тестирование в этом случае, мы должны убедиться, что у нас есть некоторая дополнительная информация о текущей просматриваемой области, которую мы отображаем. На этапе 2 нашего алгоритма нам нужно было сохранить относительный код квадранта для каждой видимой области. Это используется сейчас, чтобы правильно рассчитать центральные позиции для больших соседних видимых областей. Это также позволяет нам вычислять края видимой области, смежной с большими соседними видимыми областями. Будем условно устанавливать следующие морфинговые факторы как таковые, исходя из
на относительном коде квадранта для видимой области:

Факторы морфинга, основанные на относительных квадрантных кодах
Факторы морфинга, основанные на относительных квадрантных кодах

Вышеупомянутый набор условных тестов для случаев, когда смежная видимая область не была разделена до того же размера, что и текущая видимая область, и вместо этого имеет примененное смещение 2Rλ. Поэтому нам нужно зафиксировать коэффициенты изменения морфина равными 0, чтобы гарантировать, что все перекрывающиеся четырехугольные вершины точно совпадают с вершинами соседней видимой области большего размера. На изображении ниже представлены диаграммы различных положений, используемых с каждой видимой областью при расчете коэффициентов морфинга для граничного случая 2, на основе кода относительного квадранта для видимой области:

Граничный случай 2, код относительного квадранта


Ура! Вы сделали это до конца! Так же, как я начинал получать удовольствие от удара головой о стол! Подожди, что ты спрашиваешь? Пример кода? Хорошо обязательно! Ну вот — Версии VC ++ 2008 и VC ++ 2010 включены. Наслаждайтесь!

14

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]