1
$\begingroup$

I am writing a very simple rendering engine. I have already made a few tests, but somehow the images it creates look wrong. Objects that are further away from the camera look larger than objects closer to the camera. I have constructed this example:

pos = [-10, 0, 0] # Camera position
target = [1, 0, 0] # Camera looks at this point
up = [0, 0, 1] # z direction is "up"

fov_y = 25 * degree # field of view in y direction (camera y axis)
aspect_ratio = 1
near = 0.01 # Near clipping plane distance
far = 5000 # Far clipping plane distance

I added two lines to the scene, a red one from [1, 0, 0] to [1, 0, 1] and a black one from [4, 0, 0] to [4, 0, 1]. The black one is clearly further away from the camera, but appears larger:

Two overlapping vertical lines starting from the same bottom point. The red one is thicker and smaller than the black one.

From the above description, at first I have constructed the view matrix

V = [[0, -1, 0,   0],
     [0,  0, 1,   0],
     [1,  0, 0, -10],
     [0,  0, 0,   1]]

which seems to be correct. The perspective matrix I calculated is

P = [[4.5107,      0,         0,     0],
     [0,      4.5107,         0,     0],
     [0,           0, -1.000004, -0.02],
     [0,           0,         -1,    0]]

I'm assuming the problem is somewhere here. The full transformation matrix is (using numpy):

T = numpy.dot(P, V)

and the transformed points:

p_transformed = numpy.dot(p_untransformed, T.T) # Transpose on the right hand side

For example, [1, 0, 1] becomes [0, 4.5107, 8.98, 9] and [4, 0, 1] becomes [0, 4.5107, 5.98, 6] and since the last step is to divide the first three components by the last one, this results in the second line being larger than the first one.

Is there a mistake somewhere? If so, where is it?

Edit: Formulae

Here are the formulae I used:

enter image description here

where

d = normalized(target - pos) # direction vector of the camera
r = normalized(cross(d, up)) # x unit vector in camera space
u = normalized(cross(r, d)) # y unit vector in camera space

Furthermore, the formula for P is

enter image description here

(Source)

where

n, f # position of near an far clipping plane
t = n * tan(0.5 * radians(fov_y))
b = -t
r = t * aspect_ratio
l = -r
$\endgroup$
  • 1
    $\begingroup$ Write out formally the formulae you use to construct the view and projection matrices. $\endgroup$ – lightxbulb Jun 21 at 19:22
  • 2
    $\begingroup$ You're missing a minus in your view matrix. Just make the view matrix the inverse of the camera matrix. Also, your projection matrix flips the coordinate system so your camera starts looking in the opposite direction. Try fixing the missing sign first. $\endgroup$ – lightxbulb Jun 21 at 20:21
  • 2
    $\begingroup$ They did not make P_z positive when computing the view matrix. Rather than flip cross products, correctly set those up so no sign flips would need to leak into your matrices later on. $\endgroup$ – lightxbulb Jun 21 at 20:54
  • 1
    $\begingroup$ The projection matrix is correct. I checked it and got the same results with some minor floating point variations. @lightxbulb is right about the wrong sign. $\endgroup$ – wychmaster Jun 21 at 22:25
  • 1
    $\begingroup$ Write an answer to it yourself and self-accept it so this doesn't have to stay open. $\endgroup$ – lightxbulb Jun 22 at 0:09

Your Answer

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

Browse other questions tagged or ask your own question.