Проблемы с проекцией и обрезкой?

В настоящее время я разрабатываю механизм рендеринга Direct3D 11 с использованием С#.

Мне уже удалось нарисовать треугольники, применить цвет и текстуру и т. д. Объект, который я сейчас пытаюсь отобразить, представляет собой повернутый куб с длиной стороны 1, помещенный в начало координат мирового пространства. Но я получаю неудовлетворительные результаты при применении представления и особенно матрицы проекции. Поскольку это сложно объяснить, я просто покажу вам, какой результат я получаю для разных комбинаций вида/проекции:


Фрагмент HLSL из моего вершинного шейдера:

float4x4 wvpMatrix = mul(World, mul(View, Projection));
output.Position = mul(input.Position, wvpMatrix);

Матрица мира, которую я использую:

// Static rotation around all three axes
matrices.World = Matrix.Identity * Matrix.CreateFromYawPitchRoll(0.5f, 0.6f, 1.0f);

Тест А

Простой вектор вида от начала координат в положительном направлении z. Проекция не используется. Вы можете видеть, что задняя часть куба обрезается.

matrices.View = Matrix.CreateLookAt(new Vector3(0, 0, 0), new Vector3(0, 0, 1), Vector3.Up);
matrices.Projection = Matrix.Identity;

Куб с обрезанными задними углами


Тест Б

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

matrices.View = Matrix.CreateLookAt(new Vector3(0, 0, 0), new Vector3(0, 0, 1), Vector3.Up);
matrices.Projection = Matrix.CreateOrthographic(2, 2, 0.01f, 100.0f);

Куб с обрезанным передним углом


Тест С

Снова без проекции, как и в тесте A. На этот раз сцена просматривается из точки на три единицы в отрицательном направлении по оси z. Куб выглядит искаженным, когда положение камеры не установлено в исходное положение системы. Я думаю, что есть также некоторые отсечения.

matrices.View = Matrix.CreateLookAt(new Vector3(0, 0, -3), new Vector3(0, 0, 1), Vector3.Up);
matrices.Projection = Matrix.Identity;

Искаженный куб


Тест D

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

matrices.View = Matrix.CreateLookAt(new Vector3(0, 0, -3), new Vector3(0, 0, 1), Vector3.Up);
matrices.Projection = Matrix.CreatePerspectiveFieldOfView(1, 1, 0.1f, 100);

Нет видимых частей куба


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


person Lucius    schedule 02.02.2012    source источник
comment
Привет, вот несколько советов. Убедитесь, что матрица преобразования умножается в правильном порядке. При этом я имею в виду, что вершина должна быть сначала умножена на матрицу мира, результат должен быть умножен на матрицу представления и т. д. Это можно легко проверить, изменив код HLSL. Кроме того, попробуйте снова использовать ортогональную проекцию и установите ближнюю/дальнюю плоскость на 0,000001f/10000,0f. Последнее, что вы можете проверить, это используете ли вы треугольные примитивы для куба или моделируете ли вы куб как тройную полосу. В этом случае вам нужно будет визуализировать его с помощью треугольника или треугольника-полосы.   -  person brano    schedule 02.02.2012
comment
Привет, текущий порядок был мир, вид, проекция. Я даже разделил умножение на части, ничего не изменилось (как я и ожидал). Кроме того, изменение ближней и дальней плоскости не повлияло на результат. Только в диапазоне от 0 до 0,45 клиппинга было больше (больше, чем на втором изображении). Топология — TriangleList.   -  person Lucius    schedule 02.02.2012
comment
не могли бы вы опубликовать координаты куба?   -  person brano    schedule 03.02.2012
comment
Спасибо, сам разобрался ;)   -  person Lucius    schedule 03.02.2012


Ответы (1)


Матрицы должны быть транспонированы в какой-то момент.

Причина:

Макет структуры Microsoft.Xna.Framework.Matrix основан на строках. Матрицы в HLSL основаны на столбцах.

Из документации XNA:

Матрицы используют макет вектора-строки в XNA Framework.

Из статьи Википедии о порядке матриц:

Порядок столбцов — это аналогичный метод выравнивания массивов в линейной памяти, но столбцы перечислены в определенной последовательности. Языки [...] затенения GLSL и HLSL используют упорядочение по столбцам.


Решение А:

Транспонируйте все матрицы перед их отправкой в ​​шейдер:

var projection = Matrix.CreatePerspectiveFieldOfView(1, 1, 0.1f, 100);
projection = Matrix.Transpose(projection);

Решение Б:

Поместите эту строку в код вашего шейдера:

#pragma pack_matrix( row_major )
person Lucius    schedule 03.02.2012