Setting up an OpenGL matrix for tiling

After reading datenwolf 2011 's answer regarding setting tile-based rendering in OpenGL, I tried to implement its solution. The original image looks like this (at 800 x 600)

Original image

The resulting image with 2x2 tiles, each 800 x 600 tile per tile looks like this.

Resulting 4 images joined together

As you can see, they do not exactly match, although I see that something vaguely interesting happened. I'm sure I made a basic mistake somewhere, but I can’t see it.

I do 4 passes, where:

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

The algorithm for calculating the truncated cone for each tile:

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);

where 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;
}

For completeness, my Matrx4x4 layout:

struct
{
    T m11, m12, m13, m14;
    T m21, m22, m23, m24;
    T m31, m32, m33, m34;
    T m41, m42, m43, m44;
};

Can anyone spot my mistake?

Edit

, derhass - - . , 2x, ( ):

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 ) - , , , , , - .

Resulting image

+4
1

, , . , datenwolf fooobar.com/questions/1359668/..., , , . .

Forword: OpenGL, M v'= M *v ( ).

P, , .

, [-1,1] ^ 3 NDC. ( , P ), . 4x4 , w , NDC.

2D-, z -, x y. A B C C=A*B, , , B, A last ( C*v == A*B*v == A*(B*v)). , , P, :

P'=S(sx,sy,1) * T(tx,ty,0) * P

P' P, , -. - . , .

M times n. , sx=m sy=n. S * T ( ), T, (tx,ty) - , ( ). NDC 2 , x,y

tx= - (-1 + 2/(2*m) + (2/m) * x)
ty= - (-1 + 2/(2*n) + (2/n) * y)
//     ^     ^         ^    
//     |     |         |
//     |     |         +- size of of each tile in NDC space
//     |     |
//     |     +- half the size (as the center offset)
//     |
//     +- left/bottom border of NDC space
+3

All Articles