1
$\begingroup$

I'd like to calculate FOV in degrees of the default 3D Viewport (not a camera). According to this link the formula requires me to provide sensor width and focal length. Focal length can be seen in the view tab:

enter image description here

I don't see the value of sensor width though. Where can I find it? Or perhaps is there a way to get a value in degrees on radians straight away (perhaps from the Python code...?)

Edit

To clarify furhter, the value I'm interested in should allow me to replicate what I'm seeing in the default 3D Viewport in a separate rendering engine. For example, with OpenGL one can create a perspective matrix using following code:

glm::mat4 projection = glm::perspective(glm::radians(FOV), (float)screen_width / (float)screen_width, 0.1f, 1000.0f);

How is 3D Viewport Focal Length translating to this FOV value? For a Viewport size equal to 2115x1180 sensor width seems to be equal to 40 mm and I can generate a matching image of the default cube in OpenGL using the value of 43.60281897270362 (from math.degrees(2 * math.atan(40 /(2 * 50)))). If I resize Blender's 3D Viewport the cube generated in OpenGL and cube as seen in Blender no longer match. So what's a correct formula...?

For the reference, Viewport size can be obtained with

view = next(area for area in bpy.context.window.screen.areas if area.type == 'VIEW_3D')
window = next(view for view in view.regions if view.type == 'WINDOW')
(window.width, window.height)

Edit

To illustrate the problem further: if I resize my Blender Viewport to 1376x894 then to generate a matching image in OpenGL I need to pass down an angle of about 37.75, meaning that for constant Focal Length equal to 50 mm I have sensor width equal to about 34.19. So given these three input parameters (width=1376, height=894, focal_length=50), how do I obtain this output value of 34.19?

$\endgroup$
4
  • 1
    $\begingroup$ The view tab corresponds to the viewport's "camera" used to view the scene (not a real camera object). Click on your camera object and check the green camera button in the bottom right pane. $\endgroup$ Feb 14, 2022 at 20:54
  • $\begingroup$ Sensor width is in the camera properties (Properties Panel > Object Data / Camera Icon > Camera > Sensor Size). The 3D viewport doesn't have this value though. It seems that the stock camera has a sensor width of 36mm. $\endgroup$
    – Jeff Lange
    Feb 15, 2022 at 6:45
  • $\begingroup$ Please see my edited question. I don't care about cameras, what I want to achieve is replicating of what I'm seeing on Viewport with OpenGL and I'm not sure how to obtain the FOV value to calculate my perspective matrix depending on Viewport resolution. $\endgroup$
    – Presto
    Feb 15, 2022 at 8:34
  • $\begingroup$ I think you may have to calculate that yourself, my intuition is that it's not exposed to the API. you may find interesting things there blender.stackexchange.com/a/250935/86891 on rapid inspection the window_matrix prop seems to update when the area is resized. $\endgroup$
    – Gorgious
    Feb 15, 2022 at 8:52

2 Answers 2

2
+75
$\begingroup$

According to source, default sensor size is 36x24:

https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/makesdna/DNA_camera_types.h#L173

Width is used to calculation viewport camera:

https://github.com/blender/blender/blob/594f47ecd2d5367ca936cf6fc6ec8168c2b360d0/source/blender/editors/space_view3d/view3d_utils.c#L1188

$\endgroup$
2
  • $\begingroup$ Interesting! But you can easily see that resizing the viewport is somehow affecting this value (you can see the default cube getting smaller to fit nicely in reduced space). I'm trying to figure out either what's the final result or how to disable this effect. $\endgroup$
    – Presto
    Feb 15, 2022 at 13:08
  • $\begingroup$ Well, Blender takes the biggest side of viewport (width or height) for calculation $\endgroup$
    – Crantisz
    Feb 15, 2022 at 13:15
0
$\begingroup$

The formula that works for me:

min(width, height)/max(width, height) * 72

My C++ code is looking like this:

float Renderer::calculate_fov(uint16_t width, uint16_t height) {
    float aspect_inverted = static_cast<float>(std::min(width, height)) / static_cast<float>(std::max(width, height));
    // 72 is a default value for 1:1 aspect ratio in Blender
    float sensor_width = 72 * aspect_inverted;
    float focal_length = 50;
    return 2 * atan(sensor_width/(2*focal_length));
}

void Renderer::init(uint16_t width, uint16_t height) {
    // ...
    glm::mat4 projection_matrix = glm::perspective(
        calculate_fov(width, height),
        float(width)/float(height),
        0.1f,
        1000.0f
    );

    // https://stackoverflow.com/a/19532463/1542900
    // view = next(area for area in bpy.context.window.screen.areas if area.type == 'VIEW_3D')
    // look_at = view.spaces[0].region_3d.view_location
    // location = self.camera_position(view.spaces[0].region_3d.view_matrix)
    // up = view.spaces[0].region_3d.view_rotation @ mathutils.Vector((0.0, 1.0, 0.0))
    glm::mat4 view_matrix = glm::lookAt(location, look_at, up);

    // ...
}
$\endgroup$

You must log in to answer this question.

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