jstarick
jstarick

Reputation: 140

C++ / GLM : Calculate screen position of vertex

I want to calculate the impact of a mesh on the final render, that is, it's size in the viewport. For this, I try to get the projected position on the screen for each vertex. For example, a point rendered at center of the screen should return (0,0), in the upper right corner of the screen (1,1) and so on.

This is my code, stripped down to it's bare minimum, and based on about every example code provided for glm::perspective :

glm::mat4 Projection = glm::perspective(
    glm::radians(45.0f), 
    800.0f/600.0f, 
    0.1f, 
    100.0f
);
glm::mat4 View = glm::lookAt(
    glm::vec3(-10,0,3),
    glm::vec3(0,0,3),
    glm::vec3(0,0,1)
);
glm::mat4 MVP = Projection * View * glm::mat4(1.f);

for each (Vertex vert in *verts) {
    glm::vec3 vertPos = vert.getPosition();
    glm::vec4 screenPos = MVP * glm::vec4(vertPos, 1);
}

At this point I am stuck, since I don't know how to handle the resulting vector. I can't figure out the meaning of it's four values.

example setup: rendering

example setup: front-view

example setup: top-view

In my example setup, the point (-1,-1,2) (see red circle on first picture) is roughly rendered at pixel (480,380). The screenPos of said point returns (1.81, -2.41, 10.82, 11.0) (rounded values). I can't proceed with those results as long as I can't understand them. Does anyone know what the x,y,z and w values say about my point exactly?

I appreciate any help or hint, working too long on this issue.

PS: I know there are a lot of questions covering glm::perspective, but I don't want to render the mesh. I don't even want to include GLSL. It is just about the calculation.

Upvotes: 1

Views: 1089

Answers (1)

Michael Nastenko
Michael Nastenko

Reputation: 3043

You can divide screenPos by it's w component and you'll get your screen-space coordinates.

screenPos = screenPos / screenPos.w;

This is perspective division. This division transforms camera frustum to a post-projection cube. After it screenPos.xy will become screen space coordinates and screenPos.z - normalized depth (0.0 - near plane, 1.0 - far plane, and, btw, it's not linear).

But it'll be correct only for vertices with positive screenPos.w (i.e. for vertices before camera).

Upvotes: 1

Related Questions