If you open the modern Blender UI and select for example scaling, and then you use the scroll wheel to "zoom" (move the camera along the radial axis). You will notice that the size of the 3D widget remains constant in screen space (it becomes bigger or smaller in regards to all the other objects).

I am wondering how this can be achieved. I assume there is an obvious matrix cancellation you can do, e.g setting the w component to 1 after projecting. But I am not sure.

As you can see the widget's size in screen space is identical: enter image description here enter image description here

  • $\begingroup$ doesn't the widget simply live in screen space? i.e after projection of all the other things we simply add the widget into screenspace? $\endgroup$ – AverageGatsby May 31 at 9:00
  • $\begingroup$ Think @AverageGatsby is right. After rendering the scene, you can just add one additional render pass to draw the UI without any 3d transformations. $\endgroup$ – wychmaster May 31 at 9:31
  • $\begingroup$ Those widgets are 3D, i.e they are placed in the world and live in world space. They however remain constant size in screen dimensions. $\endgroup$ – Makogan May 31 at 18:27
  • $\begingroup$ I wasn't sure which parts you meant. Thought you are talking about the widgets on the side and referred to them as 3d widgets because they are drawn in the render window. ;) $\endgroup$ – wychmaster May 31 at 21:40

Scale the object proportional to its depth (z in camera space) and it will retain the same size on screen regardless of its position in world space.

Additionally, you might also wish to scale the object proportional to the field of view so that it retains the same screen size regardless of the camera zoom. (Specifically, scale it by tan(fov/2)).

Finally, you might also wish to scale it inversely proportional to the pixel size of the window if you want the widget to retain a constant size in pixels regardless of how large the window is. Otherwise it will be constant as a fraction of the window size.

I wouldn't recommend trying to do this in post-projective space (by manipulating w, etc) because it will scale the object's distance from the camera at the same time as scaling its size. Effectively you're scaling it in camera space. What you really want to do is scale it in its own local space before applying world-view-projection transformations.

| improve this answer | |
  • $\begingroup$ I am confused. "Scale the object proportional to its depth (z in camera space) and it will retain the same size on screen regardless of its position in world space" Assume pos is the world space position, vpos the view space position and spos the screen projected position. I tried gl_Position *= spos.z; vpos *= vpos.z; and gl_Position *= 1.f / gl_Position.z None are giving me a constant size image. Some just make everything disappear :p $\endgroup$ – Makogan Jun 1 at 3:07
  • $\begingroup$ Scale the object in local space, by the camera z of its world position. $\endgroup$ – Nathan Reed Jun 1 at 3:42

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.