简体   繁体   中英

Z value always 1 or -1 when using `glm::perspective`

I'm trying to teach myself the ways for 3D programming with OpenGL, however I am struggling with some things, especially projection matrices.

I defined some vertices for a cube and successfully handed them to my graphics processor. The cube goes from xyz -0.5 to xyz 0.5 respectively, which gets rendered fine.

To move it into my world coordinate system, I am using this model matrix:

auto model = glm::mat4(
    glm::vec4(1, 0, 0, 0),
    glm::vec4(0, 1, 0, 0),
    glm::vec4(0, 0, 1, 0),
    glm::vec4(0, 0, 0, 1)
);
model = glm::translate(model, glm::vec3(0.f, 0.f, 495.f));
model = glm::scale(model, glm::vec3(100.f, 100.f, 100.f));

This successfully moves my cube to (-50, -50, 445) -> (50, 50, 545) so its now centered in the 200x200x1000 world coordinates I defined for myself.

My camera / view matrix is

auto view = glm::lookAt(
    glm::vec3(0.f, 0.f, 5.f),
    glm::vec3(0.f, 0.f, 0.f),
    glm::vec3(0.f, 1.f, 0.f)
);

which moves the cube slightly closer, changing the z coordinate to 440 and 540 respectively. I don't understand why this is happening but I guess it has something to do with glm expecting a right hand coordinate system while I am working with a left handed one? While this is not why I am posting this question, I would be happy if someone would clear it up for me.

Now to my actual problem: I am trying to make use of glm::perspective . I call it like this:

auto perspective = glm::perspective(glm::radians(55.f), 1.f, 0.f, 1000.f);

If I'm not mistaken, at az value of 440 I can expect the clipping area to go from roughly -229 to 229 , so I would expect that bottom right cube vertex at (-50,-50) is visible. I calculated this by drawing the frustum in 2D, when I noticed that I should be able to calculate the height of any distance to the camera using tan(alpha / 2) * distToCamera = maxVisibleCoordinate (working with a 1:1 aspect ratio). Is this a correct assumption? Here is my terrible drawing, maybe you can tell that I have a wrong understanding of something with it:

我希望你能看到我想要做什么

In the final step I am trying to get all this together in my vertex shader using

gl_Position = projection * view * model * vec4(pos.x, pos.y, pos.z, 1.0);

which yields a perfectly reasonable result for the x and y value but the z value is always -1 which is, as far as I know, just right for not being displayed.

For my front-bottom-left vertex of the cube (-0.5, -0.5, -0.5) the result is (-96.04, -96.04, -440, -440) , normalized to (-0.218, -0.218, -1) .

For my back-top-right vertex of the cube (0.5, 0.5, 0.5) the result is (96.04, 96.04, -550, -550) , normalized to (0.218, 0.218, -1) .

What am I getting wrong, that my z value is lost and just set to -1 instead? When playing around with the camera position, the best I can get is getting it to 1, which also results in an empty window and is definitely not what I would expect.

A projection matrix is like this:

在此处输入图像描述

In the picture, f is for zfar and n is for znear.

As you can see, if you put znear = 0 , the term at the 4th column become zero, which is incorrect. Also, -(f+n)/(fn) = -1 , which is incorrect too.

So, the conclusion is, znear cannot be zero. It is usually a small value, for example, 0.1

Since Amadeus already answered the question correctly, I'm going to just use this space to add some clarifying information about why it's correct.

We can refer back to the diagram you provided to explain what the problem is: You have two planes, the near plane and the far plane, representing the range at which you may view objects. What the Perspective Matrix does is it takes everything in between those two planes, within the Frustrum that you've defined (mathematically a cone, but our monitors are rectangular, so...) and maps them onto the flat Near-plane to create the final image. In a sense, you can think of the Near Plane as representing the monitor.

So given this context, if you were to set the Near Plane's distance to 0, meaning it was identical to the camera, what would happen? Well, in a cone it would set the plane to a single point, and in a frustrum, it's the same. You cannot view objects drawn onto a single point. You need a surface with actual surface area to draw onto.

That is why it is inappropriate to set the near value to 0. It would turn the drawing surface into a single point, and you cannot mathematically render any objects on a single point. Hence why the essential mathematical formulas backing the matrix will break down and result in bad outcomes if you try to do so anyways.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM