Как HLSL обрабатывает произвольно малые числа?
Прежде всего, я отрисовываю единичный квадрат, применяя преобразование мира, чтобы перевести его в середину экрана. До этого момента все работало нормально. Вот изображение результата.
Однако, когда я применяю преобразование представления, я начинаю сталкиваться с некоторыми проблемами. Это код, где я создаю матрицу вида.
XMFLOAT4X4 viewMatrix;
XMVECTOR eye = XMLoadFloat3(&m_Eye);
XMVECTOR focus = XMLoadFloat3(&m_LookAt);
XMVECTOR up = XMLoadFloat3(&m_Up);
XMStoreFloat4x4(&viewMatrix, XMMatrixLookAtLH(eye, eye + focus, up));
И поэтому я отследил проблему до создания вектора lookAt в следующем коде.
float x = cos(XMConvertToRadians(m_Yaw)) * cos(XMConvertToRadians(m_Pitch));
float y = sin(XMConvertToRadians(m_Pitch));
float z = sin(XMConvertToRadians(m_Yaw)) * cos(XMConvertToRadians(m_Pitch));
XMVECTOR m_LookAt = -XMVector3Normalize(XMVectorSet(x, y, z, 0.0f));
Применяя следующие параметры...
m_Yaw = -90.0f
m_Pitch = 0.0f
m_Eye = (0.0f, 0.0f, -5.0f)
... результат в (-4.37113883e-008, 0.0, -1.0)
посмотрите на вектор, в
{ 1.0, 0.0, 4.37113883e-008, 0.0}
{ 0.0, 1.0, 0.0, 0.0}
{-4.37113883e-008, 0.0, 1.0, 0.0}
{-2.18556949e-007, 0.0, 5.0, 1.0}
посмотреть матрицу и следующее изображение.
Итак, я попытался создать жестко закодированный вектор lookAt с теми же параметрами m_Yaw и m_Pitch.
x = cos(-90) * cos(0) = 0 * 1 = 0
y = sin(0) = 0
z = sin(-90) * cos(0) = -1 * 1 = -1
Разница лишь в том, что значение х привело к 0
вместо -4.37113883e-008
Я считаю, что это связано с преобразованием в радианы. Одно это "решает" проблему, и результирующее изображение идентично первому.
Однако, так как я не могу сохранить эти значения фиксированными. Я создал небольшую константу const float kEpsilon = 0.0001f;
и обнуляет любые компоненты из вектора lookAt, которые меньше, чем kEpsilon
и больше чем -kEpsilon
,
XMVECTOR lookAt = XMVectorSet(
x < kEpsilon && x > -kEpsilon ? 0.0f : x,
y < kEpsilon && y > -kEpsilon ? 0.0f : y,
z < kEpsilon && z > -kEpsilon ? 0.0f : z,
0.0f
);
Но это похоже на дешевое решение, и я до сих пор не понимаю, почему эта ошибка возникла. Это связано с какой-то особенностью DirectX, о которой я мог не знать? Или ошибка в моем коде?
Дополнительная информация:
- Вершинный шейдер: https://pastebin.com/Lrd79HMB