Система координат D3D11

Часть моего старого кода закончилась кучей неприятных хаков, чтобы заставить вещи работать «правильно», с точки зрения перемещения объектов и камеры, например, необходимость принимать «std::sin(-yaw)», а не «std::sin(yaw)» при реализации уравнений, найденных в других местах в Интернете, и тому подобное, и, как правило, во многих случаях просто запутывали все до точки следа и ошибки.

  1. Работая с D3D11 и материалом DirectXMath (то есть левые координаты и основные строки?), что именно представляет собой предполагаемая система координат, например. если предположить, что камера находится в начале координат и смотрит вдоль желтого вектора на изображении без вращения, метки верны?

    введите здесь описание изображения

    И затем, учитывая это и камеру, описываемую (x, y, z) и шаг (мышь/управление по оси Y), рыскание (мышь/управление по оси X), и предполагая, что нет другого способа, которым я должен был бы заниматься даже то, что...

  2. Какова правильная функция для получения матрицы вида (в настоящее время я умножаю матрицу перевода и 2 матрицы поворота, умножая на проекцию, затем любые мировые матрицы для рассматриваемого объекта и транспонируя результат для использования в качестве одной константы шейдера).

  3. Каково уравнение для получения вектора, на который смотрит камера (текущее умножение вектора (0,0,1) на матрицу из 2).

  4. ... и векторы «вверх» и «вправо» (поскольку, даже если не используется функция просмотра матрицы просмотра, кажется, что отбраковка усеченной пирамиды должна знать их). Снова на данный момент умножение с матрицей от 2.
  5. Вычислите правильные скаляры/компоненты тангажа и рыскания по вектору направления (например, для башни с отдельными соединениями тангажа/рыскания).

РЕДАКТИРОВАТЬ: образцы кода:

//Moving a floating object with only yaw forwards (moveX,moveY,moveZ).
//Negative yaw seems wrong?
auto c = std::cosf(-yaw);
auto s = std::sinf(-yaw);
pos.x += moveX * c - moveZ * s;
pos.y += moveY;
pos.z += moveX * s + moveZ * c;

//Gets the vector the camera is looking along
//This time yaw is positive, but pitch is negative?
float c = std::cos(-pitch);
Vector3F facing(
    c * std::sinf(yaw),
    std::sinf(-pitch),
    c * std::cosf(yaw));

//Creating the view transform matrix, everything is negative
XMMATRIX xmviewrot;
xmviewrot = XMMatrixRotationY(-yaw);
xmviewrot*= XMMatrixRotationX(-pitch);
XMMATRIX xmview;
xmview = XMMatrixTranslation(-x, -y, -z);
xmview *= xmviewrot;
XMStoreFloat4x4A(&view, xmview);

//Other vectors needed for frustum culling
XMVECTOR xmup = XMVector3Transform(XMLoadFloat4A(&UP), xmview);
XMVECTOR xmright = XMVector3Transform(XMLoadFloat4A(&RIGHT), xmview);

//Matrix for stuff that is already in world space (e.g. terrain)
XMMATRIX xmviewProj = xmview * xmproj;
//Apparently needs transposing before use on the GPU...
XMStoreFloat4x4A(&constants.transform, XMMatrixTranspose(xmviewProj));

//In the shaders
output.pos = mul(input.pos, transform);

//vertex positions for an upwards facing square with triangle strip
v0 = (x1, y, z1);
v1 = (x1, y, z2);
v2 = (x2, y, z2);
v3 = (x2, y, z1);

Так что мне кажется, что я сделал что-то принципиально неправильное здесь, чтобы нужны -yaw и +yaw, -pitch и +pitch в разных местах? И некоторые из этих функций, которые я в конечном итоге выполнил с трассировкой и ошибкой, чтобы сделать этот бит правильным, онлайн-образцы не использовали отрицательные значения.


person Fire Lancer    schedule 27.08.2014    source источник


Ответы (2)


В Direct3D 11 нет определенной системы координат, вы можете использовать все, что захотите. Из записи в блоге Чака Уолборна на Начало работы с Direct3D 11:

Математика: Поскольку Direct3D 11 не имеет графического конвейера с «фиксированной функцией», как в Direct3D 9, выбор графических математических условных обозначений (левосторонние или правосторонние, матрицы по строкам и по столбцам и т. д.) полностью зависит от разработчика. DirectXMath можно использовать для создания преобразований «левосторонних координат» в стиле Direct3D, а также преобразований «правосторонних координат» в стиле OpenGL с использованием матричного соглашения по строкам, которое можно использовать непосредственно с шейдерами по строкам или транспонировать в используйте шейдеры столбцов.

Ваши шейдеры определяют, какую систему координат они ожидают. В конечном итоге они должны предоставлять вершины на этапе растеризации в однородном пространстве отсечения, которое Direct3D 11 определяет как:

Предполагается, что вершины (x, y, z, w), попадающие на этап растеризатора, находятся в однородном клип-пространстве. В этом координатном пространстве ось X указывает вправо, Y указывает вверх, а Z указывает в сторону от камеры.

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

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

person Ross Ridge    schedule 27.08.2014
comment
Хорошо, но должно быть небольшое количество стандартных способов, мне кажется неправильным инвертировать углы для триггера (например, преобразование шага / рыскания в вектор направления)? - person Fire Lancer; 27.08.2014
comment
И в D3D9 мне никогда не нужно было это транспонирование, но пример D3D11, кажется, использует его, и я не мог заставить все работать ожидаемым образом без него? Кроме того, многие образцы, кажется, требуют огромных усилий, чтобы использовать XMMatrixLookAtLH для перевода и 2 вращений (камера от первого лица), действительно ли это так? - person Fire Lancer; 27.08.2014
comment
Если ваши модели предполагают систему координат, отличную от используемой в вашем коде, вам придется отменить определенные значения, чтобы преобразовать их в правильную систему координат. Но поскольку вы, по-видимому, не знаете, какую систему координат использует ваш код, возможно, вы не используете согласованную систему координат. Что касается огромного объема работы, которую, похоже, выполняют образцы, возможно, они просто пытаются показать преобразования по отдельности. Это не повлияет на производительность, если они не применяются в шейдере по отдельности. - person Ross Ridge; 27.08.2014
comment
Ну да, я знаю, что модели часто нуждаются в настройке, и у меня есть это, я просто говорю об основных вещах, таких как Vector3F makeDirVec (плавающий шаг, плавающее рыскание), принимающий значения -pitch и -yaw в триггере для создания вектора направления , кажется мне неправильным, как будто у меня было вращение в неправильном направлении на моей картинке выше, чтобы начать с. Чуть позже я добавлю фактические фрагменты кода. - person Fire Lancer; 27.08.2014
comment
Я добавил несколько различных фрагментов кода, тот факт, что я использую положительные и отрицательные формы некоторых значений в разных местах, сбил меня с толку. - person Fire Lancer; 27.08.2014
comment
Что бы это ни стоило, у вас есть шаг назад на вашей диаграмме, предполагая, что вы хотели использовать левосторонние координаты, как показывают ваши оси. Если вы хотели использовать правосторонние координаты, то и направление оси Z, и ваше направление рыскания будут обратными. - person MooseBoys; 28.08.2014

Недавно я снова вернулся к DirectX (версия 12) после длительного периода отсутствия в среде разработки Microsoft.

Я заметил, что, хотя я все настроил правильно, я получаю странные и непредсказуемые результаты при выполнении геометрических преобразований. Как и вы, я отправлял матрицы MODEL VIEW PERSPECTIVE в вершинный шейдер, используя постоянный буфер.

Чтобы исправить проблему, мне пришлось использовать XMMatrixTranspose() для каждой из матриц ПЕРСПЕКТИВНОГО ВИДА МОДЕЛИ. Нравится...

m_constantBufferData.world = XMMatrixTranspose(worldMatrix);
m_constantBufferData.view = XMMatrixTranspose(viewMatrix);
m_constantBufferData.projection = XMMatrixTranspose(projectionMatrix);

Кажется, что шейдеры используют форму, противоположную основным столбцам (или основным строкам?), чем библиотечные функции DirectXMath.

Сначала я был удивлен, узнав об этом.

Для полноты вот мой код шейдера...

cbuffer SceneConstantBuffer : register(b0)
{
    float4 offset;
    matrix world;
    matrix view;
    matrix projection;
};


struct VS_INPUT
{
    float4 Pos : POSITION;
    float4 Color : COLOR;
};

struct PS_INPUT
{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR;
};


PS_INPUT VSMain(VS_INPUT input)
{
    PS_INPUT output;
    output.Pos = mul(input.Pos, world);
    output.Pos = mul(output.Pos, view);
    output.Pos = mul(output.Pos, projection);
    output.Color = input.Color;

    return output;
}

float4 PSMain(PS_INPUT input) : SV_TARGET
{
    return input.Color;
}
person Andrew    schedule 03.05.2020