asny / three-d

2D/3D renderer - makes it simple to draw stuff across platforms (including web)
MIT License
1.34k stars 110 forks source link

Camera position_at_pixel() is missing window_scale_factor on HiDPI displays #443

Closed miwarnec closed 8 months ago

miwarnec commented 9 months ago

Hey there, thanks again for your great work on three-d! I'm using Camera::position_at_pixel() on an M1 Macbook Pro (Retina / HiDPI with window scale factor = 2).

The function returns a completely wrong position, and I did some debugging to figure out why. I have a solution but I'm not sure if this is 100% correct, so I'm opening this as an issue instead of a PR for now.

position_at_pixel() first translates to UV coordinates The first bug is here: on HiDPI displays, this only ever returns values from [0, 0.5] instead of [0,1]. The solution is quite simple: multiple the result by window_scale_factor. This gives me uvs in range of [0,1].

Using the corrected version, Camera::position_at_uv_coordinates() gives me a world position. The second bug is here: this time it gives me twice the position of where things are. The solution is again quite simple: divide the result by window_scale_factor. This gives me correct 3D positions.

===> For the pixel to UV conversion, it's obvious that dividing by window_scale_factor needs to happen. ===> For the UV to world position, it's not obvious to me why this is needed. Fact is I need to divide exactly by 2, and that is also my window_scale factor. Do you think the assumption is correct, that we always need to divide by window_scale_factor here too? And if so, why is that?

Thanks!

asny commented 9 months ago

This functionality is used in the picking example which works just fine. I think it's just because you give wrong input to position_at_pixel, the pixel should be in physical pixels (multiplied by the DPR) and not in logical pixels.

miwarnec commented 8 months ago

Got it, thanks!