I'm trying to write custom OpenGL renderer that produces the exact same images as blender. However I struggle with getting camera right.

I duplicated this code and I managed to produce the exact same matrix as in calc_matrix_camera

render = bpy.context.scene.render
depsgraph = bpy.context.evaluated_depsgraph_get()
proj_matrix = bpy.context.scene.camera.calc_matrix_camera(depsgraph,x=render.resolution_x,y=render.resolution_y,scale_x=render.pixel_aspect_x,scale_y=render.pixel_aspect_y)

I get the model-view matrix identical as in bpy.context.scene.camera.matrix_world but for testing purposes I always place camera at the origin point with no rotation (so model-view matrix is the identity matrix). However I still cannot get the renderings right. What I find suspicious is that


returns a different value from

2.0*math.atan( 1.0/proj_matrix[1][1])

(explanation of math here). I suspect there is some extra logic that I'm not taking into account. How do I get aspect ratio and fov from blender? Which of those values is correct?


1 Answer 1


There is indeed some extra logic. In general you should use camera.angle and take the settings under Camera Properties > Camera > Sensor Fit into account.

Lets set first

camera = bpy.data.cameras['Camera']
aspect = render.resolution_x / render.resolution_y

If the Sensor Fit is set to Horizontal you'll have (equaling angle_x)

camera.angle = 2.0 * math.atan(aspect / proj_matrix[1][1])

If it's set to Vertical you'll get (equaling angle_y)

camera.angle = 2.0 * math.atan( 1.0/ proj_matrix[1][1])

Finally, if it's set to Auto it depends on the aspect ratio:

If aspect > 1 then camera.angle = camera.angle_x = 2.0 * math.atan(aspect / proj_matrix[1][1])

If aspect < 1 then camera.angle = camera.angle_x = 2.0 * math.atan(1.0 / proj_matrix[1][1])

If aspect == 1 then camera.angle = camera.angle_x = 2.0 * math.atan(aspect / proj_matrix[1][1]) = 2.0 * math.atan(1.0 / proj_matrix[1][1])

For an in-depth explanation on what Blender is doing under the hood see my answer here.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .