# understanding glm::perspective vs glm::ortho

I'm new to computer graphics. I played around with OpenGL and now am trying out Vulkan.

Basically what I want to do, in 2D is have an 800x800 window, and I want that to represent 800 meters by 800 meters. Then I want a circle with a radius of 1 meter.

I am going off of the Vulkan tutorial.

My data structure is this:

struct Vertex {
glm::vec2 pos;
};


I create my circle:

const int NUM_POINTS = 20;
uint32_t angle = 360/NUM_POINTS;
Vertex vertex;
std::vector<Vertex> vertices;

for(uint32_t i=0; i <= 360; i+=angle){
vertices.push_back(vertex);
}


Something to do with the viewport:

VkViewport viewport = {};
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = (float) swapChainExtent.width;
viewport.height = (float) swapChainExtent.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;


viewport.width and viewport.height both equal 800.0f.

Projection matrices:

struct UniformBufferObject{
glm::mat4 model;
glm::mat4 view;
glm::mat4 proj;
};


projections:

ubo.view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 10.0f);
ubo.proj[1][1] *= -1;


This shows the circle, but it's almost as big as the window and it's tilted 45° away from me.

First of all, I don't understand why, if I make the first argument to glm::lookAt be glm::vec3(0.0f, 0.0f, 2.0f), I see nothing. I mean the circle is in the x-y plane. If I move in the z-direction, shouldn't I see it?

Then I tried glu::ortho

ubo.proj = glm::ortho(0.0f, 800.0f, 800.0f, 0.0f);


But I still see nothing.

• carefull vulkan and opengl expect different Z bound in clipspace. GLM should have a #define for that somewhere. Feb 8, 2017 at 13:43

It's because of the up vector. If you think about the look-at operation, you specify where the camera is and what point it's looking towards. These two things alone leave one degree of freedom: the rotation around that axis. Which way is up on your screen? The third argument is for specifying that: it's a direction in world space which will correspond to up on the screen. If your first argument is that and the rest of the code is as your example, you're calling lookAt((0,0,2), (0,0,0), (0,0,1)). Your up vector points along the $z$-axis, which is the same direction the camera is looking (well, the opposite direction. This can't define which way is up on the screen.
You probably want to pass a vector (0,1,0) as the third argument, which will make $y$ point up on your screen.
If you're making a plan view of a 3D scene, then perspective projection is probably the right answer, but if all your content is going to be in the $z=0$ plane, then you probably want to use an orthographic rather than a perspective projection. Look at What's the difference between orthographic and perspective projection? to learn more about that.
Last of all, remember that if you're projecting an $800m \times 800m$ scene onto $800 \times 800$ pixels, then a $1m$ radius circle will only be one pixel large. You probably need to scale up the size of your circle.
• center is the point the eye is looking at, i.e. the point that will be in the middle of the screen. up is the direction (not a point) the top of the camera is pointing; i.e. if you draw a line from center in the direction up, this line will be in the 12 o'clock position on the screen. Feb 9, 2017 at 13:49