Недавно я изо всех сил пытался установить хорошую матрицу перспективной проекции и применить ее к простому треугольнику. Прежде чем показать какой-либо код, у меня есть небольшой вопрос о порядке расположения матриц: нужно ли умножать матрицу моего вида на матрицу проекции или умножать матрицу моего проекции на матрицу вида?
Хорошо, теперь код. Я пробовал много разных способов сделать перспективную матрицу без какого-либо хорошего результата.
static Matrix4x4<T> Perspective_S(const T &fovy, const T &aspectRatio, const T &zNear, const T &zFar)
{
T range = tanf(fovy / 2.0f) * zNear;
return Matrix4x4<T>((2.0f * zNear) / (range * aspectRatio + range * aspectRatio), 0.0f, 0.0f, 0.0f,
0.0f, zNear / range, 0.0f, 0.0f,
0.0f, 0.0f, -(zFar + zNear) / (zFar - zNear), -1.0f,
0.0f, 0.0f, (-(2.0f * zFar * zNear) / (zFar - zNear)), 0.0f);
}
static Matrix4x4<T> Perspective_S(const T &fovy, const T &aspectRatio, const T &zNear, const T &zFar)
{
T f = 1.0f / tan(fovy / 2.0f);
return Matrix4x4<T>(f / aspectRatio, 0.0f, 0.0f, 0.0f,
0.0f, f, 0.0f, 0.0f,
0.0f, 0.0f, (zFar + zNear) / (zNear - zFar), (2.0f * zFar * zNear) / (zNear - zFar),
0.0f, 0.0f, -1.0f, 0.0f);;
}
static Matrix4x4<T> Frustum_S(const T &left, const T &right, const T &bottom, const T &top,
const T &zNear, const T &zFar)
{
return Matrix4x4<T>(2.0f * zNear / (right - left), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f * zNear / (top - bottom), 0.0f, 0.0f,
(right + left) / (right - left), (top + bottom) / (top - bottom), -(zFar + zNear) / (zFar - zNear), -1.0f,
0.0f, 0.0f, -2.0f * zFar * zNear / (zFar - zNear), 0.0f);
}
static Matrix4x4<T> Perspective_S(const T &fovy, const T &aspectRation, const T &zNear, const T &zFar)
{
T scale = tan(fovy) * zNear;
T r = aspectRation * scale, l = -r;
T t = scale, b = -t;
return Frustum_S(l, r, b, t, zNear, zFar);
}
static void Perspective_S(Matrix4x4<T> &matrix, T fovyInDegrees, T aspectRatio, T znear, T zfar)
{
T ymax = znear * tanf(fovyInDegrees * 3.14159265358979323846 / 360.0); //c'est pas 180?
//ymin = -ymax;
//xmin = -ymax * aspectRatio;
T xmax = ymax * aspectRatio;
Frustum(matrix, -xmax, xmax, -ymax, ymax, znear, zfar);
}
static void Frustum_S(Matrix4x4<T> &matrix, T left, T right, T bottom, T top,
T znear, T zfar)
{
T temp = 2.0f * znear;
T temp2 = right - left;
T temp3 = top - bottom;
T temp4 = zfar - znear;
matrix = Matrix4x4<T>(temp / temp2, 0.0f, 0.0f, 0.0f,
0.0f, temp / temp3, 0.0f, 0.0f,
(right + left) / temp2, (top + bottom) / temp3, (-zfar - znear) / temp4, -1.0f,
0.0f, 0.0f, (-temp * zfar) / temp4, 0.0f);
}
Некоторые функции выглядят как транспонированная результирующая матрица некоторых других моих попыток. Все эти функции были взяты из учебников. Один даже пришел из моего предыдущего поста, и он все еще не работает …
На всякий случай вы можете подумать, что это мой код LookAt, вот он:
Что я делаю в main.cpp
matptr = (Matrix4x4f::LookAt_S(eye, center, up) *
Matrix4x4f::Perspective_S(M_PI / 3.0f, (float)window->getSize().x / (float)window->getSize().y, 0.001f, 1000.0f)).ToArray();
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "myMatrix"), 1, GL_FALSE, &matptr[0]);
Мой код LookAt:
static Matrix4x4<T> LookAt_S(Vector3<T> &eye, Vector3<T> ¢er, Vector3<T> &up)
{
Vector3<T> forward(center - eye);
forward.Normalize();
Vector3<T> side(forward.CrossProduct(up));
side.Normalize();
up = side.CrossProduct(forward);
return Matrix4x4<T> (side.x, up.x, -forward.x, 0.0f,
side.y, up.y, -forward.y, 0.0f,
side.z, up.z, -forward.z, 0.0f);
}
Задача ещё не решена.
Других решений пока нет …