После прочтения datenwolf's 2011 answer concerning tile-based render setup in OpenGL я попытался реализовать его решение. Исходное изображение выглядит следующим образом (при 800 х 600)Настройка матрицы OpenGL для черепичного рендеринга
Полученное изображение с 2х2 плиток, каждая плитка при 800 х 600 на плитке выглядит следующим образом.
Как вы можете видеть, что они не совпадают, хотя я могу увидеть что-то неопределенно интересное произошло. Я уверен, что где-то проделал элементарную ошибку, но я не могу ее увидеть.
Я делаю 4 прохода, где:
w, h are 2,2 (2x2 tiles)
x, y are (0,0) (1,0) (0,1) and (1,1) in each of the 4 passes
MyFov is 1.30899692 (75 degrees)
MyWindowWidth, MyWindowHeight are 800, 600
MyNearPlane, MyFarPlane are 0.1, 200.0
алгоритм для вычисления усеченный для каждой плитки:
auto aspect = static_cast<float>(MyWindowWidth)/static_cast<float>(MyWindowHeight);
auto right = -0.5f * Math::Tan(MyFov) * MyShaderData.Camera_NearPlane;
auto left = -right;
auto top = aspect * right;
auto bottom = -top;
auto shift_X = (right - left)/static_cast<float>(w);
auto shift_Y = (top - bottom)/static_cast<float>(h);
auto frustum = Math::Frustum(left + shift_X * static_cast<float>(x),
left + shift_X * static_cast<float>(x + 1),
bottom + shift_Y * static_cast<float>(y),
bottom + shift_Y * static_cast<float>(y + 1),
MyShaderData.Camera_NearPlane,
MyShaderData.Camera_FarPlane);
, где Math :: Frustum является:
template<class T>
Matrix4x4<T> Frustum(T left, T right, T bottom, T top, T nearPlane, T farPlane)
{
Matrix4x4<T> r(InitialiseAs::InitialiseZero);
r.m11 = (static_cast<T>(2) * nearPlane)/(right - left);
r.m22 = (static_cast<T>(2) * nearPlane)/(top - bottom);
r.m31 = (right + left)/(right - left);
r.m32 = (top + bottom)/(top - bottom);
r.m33 = -(farPlane + nearPlane)/(farPlane - nearPlane);
r.m34 = static_cast<T>(-1);
r.m43 = -(static_cast<T>(2) * farPlane * nearPlane)/(farPlane - nearPlane);
return r;
}
Для полноты моего матраса матраса 4x4:
struct
{
T m11, m12, m13, m14;
T m21, m22, m23, m24;
T m31, m32, m33, m34;
T m41, m42, m43, m44;
};
Может ли кто-нибудь указать мою ошибку?
Edit:
Так derhass объяснил мне - гораздо более простой способ делать вещи просто масштабировать и перевести проекционную матрицу. Для тестирования я изменил мою матрицу перевода, расширены в 2 раза, следующим образом (изменение перевода для каждой плитки):
auto scale = Math::Scale(2.f, 2.f, 1.f);
auto translate = Math::Translate(0.5f, 0.5f, 0.f);
auto projection = Math::Perspective(MyFov,
static_cast<float>(MyWindowWidth)/static_cast<float>(MyWindowHeight),
MyShaderData.Camera_NearPlane,
MyShaderData.Camera_FarPlane);
MyShaderData.Camera_Projection = scale * translate * projection;
Полученное изображение ниже (сшивание 4 вместе) - разрывы в изображении вызвано я думаю, что это будет другая проблема, с которой мне придется иметь дело в какой-то момент.
Я не проверил, что это неправильно в вашей реализации, но я думаю, что решение этого datenwolf там ненужно комплекс. Если вы визуализировали сцену с некоторой матрицей проекций (независимо от ортогональности или перспективы), полученный усеченный конус окажется в однородном представлении пространства [-1,1]^3 НДЦ. Поэтому, если вы хотите, чтобы какая-либо часть этого отображаемого полноэкранного экрана была достаточной, просто _pre-multiply_ некоторый масштаб и перевод по x и y, чтобы выбрать любой 2D-прямоугольник, который вам нравится (что будет иметь тот же эффект, что и изменение FOV и асимметрии в перспективном усечении). – derhass
Я думал, что НДЦ произошел после гомогенного разрыва, который после умножения на матрицу проекции, поэтому я не вижу, как это будет работать. Независимо от того, что я пробовал использовать масштаб WxH и различные переводы, и я не мог заставить его работать. Математика ошибочна. – Robinson
Я предлагаю применить в пространстве клипа. Я только собираю NDC для диапазона [-1,1] усеченного конуса. Ключевым моментом является применение простого перевода и масштабирования после применения матрицы проецирования (что означает, что _pre_ умножает его на стандартные соглашения GL) для масштабирования и смещения некоторого суб-прямоугольника [-1,1] до полного [-1, 1] точно отобразит эту часть изображения в полном окне просмотра. – derhass