Кастинг луч против проецирования вершин?

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

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

Вот мой конструктор «камера» (отвечает за построение матрицы проекции):

Camera::Camera(float fLength, float fov, float targetRatio, float zNear, float zFar)
{
focalLength = fLength;
fieldOfView = fov;
aspectRatio = targetRatio;
scale = tan(fieldOfView * 0.5 * DEG_TO_RAD);

viewMatrix = Matrix4<float>();

projectionMatrix = Matrix4<float>();

float distance = zFar - zNear;

projectionMatrix.xx = scale / aspectRatio;
projectionMatrix.yy = scale;
projectionMatrix.zz = -(zFar + zNear) / distance;
projectionMatrix.zw = -1.0f;
projectionMatrix.wz = -2.0f * zNear * zFar / distance;
projectionMatrix.ww = 0.0;

//aperture = tan(fieldOfView / 2 * DEG_TO_RAD) * focalLength * 2;
//fieldOfView = atan((aperture / 2) / focalLength) * 2 * RAD_TO_DEG;
}

Вот как я отбрасываю лучи на основе размеров кадрового буфера и текущих координат пикселей (я вычисляю направление и получаю положение камеры из последней строки матрицы):

Ray Camera::castRay(unsigned int width, unsigned int height, unsigned int x, unsigned int y)
{
float dirX = (2 * (x + 0.5) / (float)width - 1) * aspectRatio * scale;
float dirY = (1 - 2 * (y + 0.5) / (float)height) * scale;

Vector3<float> dir = (Vector3<float>(dirX, dirY, -1.0) * viewMatrix).normalize();

return Ray(Vector3<float>(viewMatrix.wx, viewMatrix.wy, viewMatrix.wz), dir);
}

С другой стороны, вот как я растрирую вершины, используя подход растеризации:

    Vector4<float> vertexInRasterSpace;
Vector4<float> vertexInCameraSpace;

vertexInCameraSpace = currentVertex * camera.viewMatrix;
vertexInRasterSpace = vertexInCameraSpace * camera.projectionMatrix;

vertexInRasterSpace.x = std::min(width - 1, (int)((vertexInRasterSpace.x + 1) * 0.5 * width));
vertexInRasterSpace.y = std::min(height - 1, (int)((1 - (vertexInRasterSpace.y + 1) * 0.5) * height));
vertexInRasterSpace.z = -vertexInCameraSpace.z;

Наконец, полученные результаты:

-Трассировка лучей -> Трассировка луча

-Растеризация -> Растеризация изображения

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

~ Sky

1

Решение

Зависит от того, что делает алгоритм растеризации (передаете ли вы вершины в API трехмерной графики или делаете свою собственную растеризацию?), Но мои первые подозрения:

После умножения на матрицу перспективы, но перед растеризацией необходимо выполнить перспективный разрыв: то есть деление компонентов X, Y и Z вашего вектора на компонент W. Это, кажется, отсутствует.

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

1

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

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

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