opengl - SFML::View inverted-y 轴是标准的吗?如何解决它?

标签 opengl graphics 2d viewport sfml

我使用右手坐标(x = 右,y = 上)在世界空间中放置对象。

当我必须使用 SFML 渲染它们时,我遇到了问题,因为我无法在 sf::View 中使用 (y = up) 矩阵设置 View 矩阵,然后所有内容都呈现为 y-flipped。

我想的一个解决方案是在渲染之前翻转每个对象的 y 轴:

ObjectTransformMatrix * MatrixScale(1.0f,-1.0f)

但我认为我必须将 sf::View 中心移动到:

y = y - (view_size.y / 2.0)

为什么 sf::View 是 y 轴反转的?我的解决方案正确吗?

最佳答案

Why sf::View is y-inverted ?

大多数图形包/库都有其屏幕空间坐标系,原点在左上角,X 向右,Y 向下。这只是一个惯例,SFML 恰好选择了它。请注意,这不是左撇子或右撇子;这将取决于第三轴,如果有的话。我会认为你所指的另一个坐标系是传统的数学坐标系。

flipping the y-axis on every object before rendering it

不要这样做!你有一个为你方便而定义的世界。当您可以更改将在内部隐式应用于所有渲染对象的相机 (sf::View) 转换时,为什么要更改它。来自 the documentation :

sf::View defines a camera in the 2D scene.

This is a very powerful concept: you can scroll, rotate or zoom the entire scene without altering the way that your drawable objects are drawn. [...] To apply a view, you have to assign it to the render target. Then, every objects drawn in this render target will be affected by the view until you use another view.

本质上,您会将下面的派生矩阵设置为相机的变换,但要通过通过 sf::View 公开的函数。

Is my solution correct?

部分正确,其余部分您已经猜对了。翻转轴只是解决方案的一部分,您还应该将原点平移到正确的位置。您需要的是 Mm→s,其中 m 是数学空间,s 是屏幕空间。发现需要变换屏幕空间坐标系,使其与数学坐标系对齐。由于两个坐标系中的比例相同,我们可以按原样使用宽度 W 和高度 H 的值(最初来自屏幕空间)。

我们有这个:

              S--->---- W ---------+
              |                    |
              v                    |
              |                    |
              |                    |
              |                    |
              |
              |                    H
              |
              |                    |
              |                    |
              ^                    |
              |                    |
              M--->----------------+

当我们执行 S1, −1 时,即 X 轴缩放 1,Y 轴缩放 −1(翻转 Y),我们有

              ^
              |
              S--->---- W ---------+
              |                    |
              |                    |
              |                    |
              |                    |
              |                    |
              |
              |                    H
              |
              |                    |
              |                    |
              ^                    |
              |                    |
              M--->----------------+

这个新系统不再是 S,因为它的 Y 被翻转了;让我们称之为S'。现在我们必须平移(移动)它的原点以到达 M。由于我们正在变换坐标系,而不是点,所以我们必须相对于 S'、变换后的中间坐标系而不是 S 来做。

我们做 T0, -H 即沿着负 Y 移动 H 个单位。我们最终会得到

              +-------- W ---------+
              |                    |
              |                    |
              |                    |
              |                    |
              |                    |
              |
              |                    H
              |
              |                    |
              |                    |
              ^                    |
              |                    |
              O--->----------------+

where both M and S are at O.

我们必须连接 S 和 T 以获得最终的 Mm→s。由于我们正在变换坐标系而不是点,因此我们必须进行后乘(假设您使用的是列向量约定)。

Mm→s = S1, −1 T0, -H

| 1  0  0 | | 1  0  0 |   | 1  0  0 |
| 0 −1  0 | | 0  1 −H | = | 0 −1  H |
| 0  0  1 | | 0  0  1 |   | 0  0  1 |

假设我们有一个 5×5 的屏幕(为简单起见)。将世界空间中的点 (1, 1) 转换为屏幕空间:

| 1  0  0 | |1|   |1|
| 0 −1  5 | |1| = |4|
| 0  0  1 | |1|   |1|

(1, 4) 是点在屏幕空间中的坐标。

如果您遵循行向量约定,则必须转置等式 M = AB 即 MT = BT AT。这会给我们

| 1  0  0 | | 1  0  0 |   | 1  0  0 |
| 0  1  0 | | 0 −1  0 | = | 0 −1  0 |
| 0 −H  1 | | 0  0  1 |   | 0  H  1 |

关于opengl - SFML::View inverted-y 轴是标准的吗?如何解决它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34310771/

相关文章:

c++ - 在GLFW窗口中启用多重采样不会提高抗锯齿的质量

c++ - 跨平台窗口库——集成 OpenGL 和 DirectX

algorithm - 使用多边形的中点是否始终适用于 Painter 的 HSR 算法?

c# - 如何使用图形库 C# 在图像上绘制小图像?

java - 如何使用 GUI 在 Canvas 上绘制简单图形

c++ - 如何在单独的视口(viewport)中使用帧缓冲区以及默认帧缓冲区?

c++ - OpenGL 纹理未显示(纯色而不是纹理)或显示有伪影

C++ 按列对二维 vector 进行排序

.net - 根据角度计算从矩形中的点到边缘的向量

2d - 你应该如何在 Vulkan 中更新每帧的纹理?