I'm trying to setup my renderer and I'm configuring the matrices. I currently have a View Matrix and a Projection Matrix which I then multiply and send to the shader(there's no need for model matrix since I'm just testing).

The problem is I just can't seem to get the projection matrix right. My model of a sphere appers cut in half in the center of the screen, I can move it around but once the Z value for the transform in the matrix goes beyond 1(Vulkan's max value for NDC) the model cuts off.

This is the code for the view matrix:

ViewMatrix(3, 0) = CamPos.X;
ViewMatrix(3, 1) = -CamPos.Y;
ViewMatrix(3, 2) = CamPos.Z;

The numbers on the left are the rows and those on the right the columns. Matrices are row-major. And my renderer's coordinate system is left handed.

This is the code for the projection matrix:

auto f = 1 / tan_half_fov;

_Matrix(0, 0) = f / _AspectRatio;
_Matrix(1, 1) = -f;
_Matrix(2, 2) = _Far / (_Near - _Far);
_Matrix(2, 3) = -1;
_Matrix(3, 2) = (_Near * _Far) / (_Near - _Far);

The matrix is just an identity matrix and the every frame it gets set those values. tan_half_fov is 0.41421356, since it's tan(45 deg / 2). _Near is 1, and _Far is 500.

The vertex shader:

void main()
    gl_Position = inData.Pos * vec4(inPos, 1.0);

inPos is the vertex data input for vertex position and inData.Pos is the ViewProjection matrix.

The matrix multiplication code is working alright, I tested it. When sending to the shader just the view matrix the sphere appears all flat on the screen and moves around correctly. I am using Vulkan.

Any help is appreciated!

  • \$\begingroup\$ Set the near value to something smaller (but still positive). It will cut anything off if it goes closer to the camera, than 1 unit \$\endgroup\$ – Bálint Oct 30 '19 at 10:28
  • \$\begingroup\$ @Bálint Setting the near value to 0.5 didn't solve it. The problem is, things (Vertices) seem to clip when they go beyond 1. \$\endgroup\$ – Facundo Villa Oct 30 '19 at 19:01

To solve your problem, you need to understand how a projection matrix works:

A projection matrix represents a frustum, shown in this image:

enter image description here

As you can see, it looks a bit like a pyramid with the cap cut off, or trapezium.

The near and far values tell the shader which fragments to draw, via a depth test.

Fragments, once translated to screen space, will be culled, if they have a z value of less than 0, or greater than 1.

Now let's look at "handed-ness":

enter image description here

OpenGL uses a right handed coordinate system, whilst Vulkan uses a left handed coordinate system, with the exception that the Y axis is flipped.

If your perspective transform maps a z value outwith the range of [0-1], then it will be culled, so check your perspective transform construction.

| improve this answer | |
  • \$\begingroup\$ This is wrong, Vulkan does not have Z point positive towards the viewer, it goes from [0, 1], pointing outwards, with y flipped being, -1 at the top, and 1.0 at the bottom. see this as well \$\endgroup\$ – whn Nov 8 '19 at 18:09
  • \$\begingroup\$ Thank you for the correction. I have edited my answer. \$\endgroup\$ – Ian Young Nov 9 '19 at 12:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.