# Offset a camera/render without changing perspective

I need to offset a render so that the perspective / vanishing point doesn't change. Or another way to look at it is that I need to adjust the vanishing point in my view so that instead of being at 0,0 xy it's where ever I want it to be.

Imagine a tall iPhone screen with some extruded 3d text at the top of the view. You would see the bottom sides of the extrusion because the camera is below the object. But now move the object to the bottom of the view. Now you see the top sides of the extrusion because the camera is above the object. Same if you move the camera instead of the object. The vanishing point is at 0,0 in the window.

Now let's say I wanted to draw the 3d text as it would look at the top of the screen but I want to draw it at the bottom of the screen. Forget about the cheat of rendering it to a texture and drawing that texture somewhere else. How do I shift everything up or down without changing the perspective? Is there an easy way?

In practice I only need to move the vanishing point up a little in my game. Perspective is key to being able to play. Basically when the ad banner is at the top of the screen the view is smaller height wise. That moves the vanishing point down by half the size of the ad banner, and screws up the game play.

I'm using the standard camera look at matrix function and projection matrix function that is based on the fov...

lookAtMatrix(cameraPos, camLookAt, camUpVector, mView);
matrixPerspective(cameraFOV, near, far,  aspect, mProjection);


I'm assuming that I need to change my mProjection somehow.

Wow that was fast. It's crazy how sometimes just writing out the question helps you figure out how to approach a solution.

Here is my matrixPerspective function:

void matrixPerspective(float angle, float near, float far, float aspect, mat4 m)
{
//float size = near * tanf(angle / 360.0 * M_PI);
float size = near * tanf(degreesToRadians(angle) / 2.0);
float left = -size, right = size, bottom = -size / aspect, top = size / aspect;

// Unused values in perspective formula.
m[1] = m[2] = m[3] = m[4] = 0;
m[6] = m[7] = m[12] = m[13] = m[15] = 0;

// Perspective formula.
m[0] = 2 * near / (right - left);
m[5] = 2 * near / (top - bottom);
m[8] = (right + left) / (right - left);     // 0 - THIS
m[9] = (top + bottom) / (top - bottom);     // 0 - AND THIS
m[10] = -(far + near) / (far - near);
m[11] = -1;
m[14] = -(2 * far * near) / (far - near);


}

m[8] and m[9] will offset the vanishing point in view space. So -1 to 1 in either of these to adjust it to a point inside the view. For example a -1 in m[9] will make the vanishing point be the very top of the view.

And I can make a companion function that inputs the vanishing point offset.

For my particular problem of needing to offset by the amount of the banner ad. I know the pixel size of the banner ad and the pixel height of the screen. And 2/height is one "pixel". So I just moved the vanishing point by half the pixel height of the ad. Boom goes the dynamite.

Edit: Here's the function I made for it:

void offsetProjectionCenter(float xOffset, float xTotalSize, float yOffset, float yTotalSize, mat4 m)
{
// each axis has the scale of -1 to 1 with default at zero.
// offsetting an axis by 1/TotalPixelSize would be 1/2 pixel.  So 2/Size is a full pixel.
// or totalSize/2 is just from center to the edge.  So 1/halfPixelSize is a full pixel
// the offset/(totalSize/2) or 2*offset/totalSize - is the answer
m[8] = 2.0 * xOffset / xTotalSize;
m[9] = -2.0 * yOffset / yTotalSize;         // the y axis is reversed with -1 at the top
}

• Thanks for posting the answer, this is exactly what I needed! – Levi May 31 '17 at 13:27
• Yeah I hate it when people ask a question and then figure it out but don't post the answer. So I try to always do that. – badweasel Jun 1 '17 at 5:05