Apply snap 2D transforms to pixel to viewport
We shall not leave the viewport transform to be rounded by the code for rounding canvas items. Since the viewport transform is inverse to the camera transform, we get incorrect rounding at the halfway point that misaligns the viewport and the canvas item which the camera is following. Instead, reintroduce viewport rounding, but do it in a way that matches the rounding of canvas items. Also take into account the half-pixel offset of the centre point when viewport dimension is not divisible by two. For `CanvasLayer`s that follows viewport, take into account the scale when rounding. Overall this should work better compared to the rounding in Godot 4.2 (and earlier).
This commit is contained in:
parent
d5aadc38b4
commit
1bd66af54c
|
@ -41,14 +41,31 @@
|
||||||
static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, RendererCanvasCull::Canvas *p_canvas, RendererViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
|
static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, RendererCanvasCull::Canvas *p_canvas, RendererViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
|
||||||
Transform2D xf = p_viewport->global_transform;
|
Transform2D xf = p_viewport->global_transform;
|
||||||
|
|
||||||
|
Vector2 pixel_snap_offset;
|
||||||
|
if (p_viewport->snap_2d_transforms_to_pixel) {
|
||||||
|
// We use `floor(p + 0.5)` to snap canvas items, but `ceil(p - 0.5)`
|
||||||
|
// to snap viewport transform because the viewport transform is inverse
|
||||||
|
// to the camera transform. Also, if the viewport size is not divisible
|
||||||
|
// by 2, the center point is offset by 0.5 px and we need to add 0.5
|
||||||
|
// before rounding to cancel it out.
|
||||||
|
pixel_snap_offset.x = (p_viewport->size.width % 2) ? 0.0 : -0.5;
|
||||||
|
pixel_snap_offset.y = (p_viewport->size.height % 2) ? 0.0 : -0.5;
|
||||||
|
}
|
||||||
|
|
||||||
float scale = 1.0;
|
float scale = 1.0;
|
||||||
if (p_viewport->canvas_map.has(p_canvas->parent)) {
|
if (p_viewport->canvas_map.has(p_canvas->parent)) {
|
||||||
Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform;
|
Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform;
|
||||||
|
if (p_viewport->snap_2d_transforms_to_pixel) {
|
||||||
|
c_xform.columns[2] = (c_xform.columns[2] * p_canvas->parent_scale + pixel_snap_offset).ceil() / p_canvas->parent_scale;
|
||||||
|
}
|
||||||
xf = xf * c_xform;
|
xf = xf * c_xform;
|
||||||
scale = p_canvas->parent_scale;
|
scale = p_canvas->parent_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform2D c_xform = p_canvas_data->transform;
|
Transform2D c_xform = p_canvas_data->transform;
|
||||||
|
if (p_viewport->snap_2d_transforms_to_pixel) {
|
||||||
|
c_xform.columns[2] = (c_xform.columns[2] + pixel_snap_offset).ceil();
|
||||||
|
}
|
||||||
xf = xf * c_xform;
|
xf = xf * c_xform;
|
||||||
|
|
||||||
if (scale != 1.0 && !RSG::canvas->disable_scale) {
|
if (scale != 1.0 && !RSG::canvas->disable_scale) {
|
||||||
|
|
Loading…
Reference in New Issue