在 OpenGL 中使用左上原点
Use top-left origin in OpenGL
我正在尝试设置坐标系,使 y 轴指向屏幕下方。
// Determine view-projection matrix
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
3.0f, // bottom
-3.0f); // top
// Right handed rule:
// x points right
// y points down
// z points into the screen
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, -1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, -1, 0) // up vector
);
glm::mat4 viewProjMatrix = projection * view;
但是,当我尝试渲染 2 个对象时:
A at (0, 0)
B at (1, 1)
A出现在屏幕中央,B出现在右上角。我希望它出现在右下角。
我在这里错过了什么?
tl;博士
我的相机定位正确(从某种意义上说),但我在调用 glOrtho
时翻转了 y 轴。
让我们想象一下
想象一个右手坐标系,例如 OpenGL 按照惯例使用的坐标系:
- x轴指向右边
- y轴指向上方
- z轴指向屏幕外
如果我的物体被放置在这个世界上并且我们从前面观察它们,我们会看到:
B
A
这和我看到的一样,但我们不是从正面看。正如@Scheff 在评论中指出的那样,我对 glm::lookat
的调用是将我的相机倒置并将其定位 "behind" 屏幕。
现在,如果您想象自己在显示器后面做倒立,A 和 B 现在看起来像这样:
∀
等等,但这不是我想要的吗 - 右下角的 B?
是的,但除了我的相机位置奇怪之外,我的 y 轴还因调用 glm::ortho
而翻转。通常 bottom
的值应小于 top
的值(如 this example)。
因此再次产生:
B
A
因此,一种解决方案是交换 glOrtho
中的 top
和 bottom
参数:
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, -1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, -1, 0) // up vector
);
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
-3.0f, // bottom (less than top -> y-axis is not inverted!)
3.0f); // top
如何翻转y轴"correctly"
上面的解决方案有效,但还有一个更简单的解决方案 - 或者至少更易于可视化!这只是将相机定位在场景前面并使用 glOrtho
翻转 y 轴(通过保持 bottom
大于 top
):
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, 1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, 1, 0) // up vector
);
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
3.0f, // bottom (greater than top -> y-axis is inverted!)
-3.0f); // top
潜在问题
纹理方向
翻转 y 轴可能会导致纹理上下颠倒,这可以通过交换顶部和底部纹理坐标来解决。
背面剔除
如果启用 face culling,从不同角度查看场景可能会导致面孔被剔除。这可以通过更改顶点的缠绕顺序或通过更改 哪些 个面被剔除来解决。
我正在尝试设置坐标系,使 y 轴指向屏幕下方。
// Determine view-projection matrix
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
3.0f, // bottom
-3.0f); // top
// Right handed rule:
// x points right
// y points down
// z points into the screen
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, -1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, -1, 0) // up vector
);
glm::mat4 viewProjMatrix = projection * view;
但是,当我尝试渲染 2 个对象时:
A at (0, 0)
B at (1, 1)
A出现在屏幕中央,B出现在右上角。我希望它出现在右下角。
我在这里错过了什么?
tl;博士
我的相机定位正确(从某种意义上说),但我在调用 glOrtho
时翻转了 y 轴。
让我们想象一下
想象一个右手坐标系,例如 OpenGL 按照惯例使用的坐标系:
- x轴指向右边
- y轴指向上方
- z轴指向屏幕外
如果我的物体被放置在这个世界上并且我们从前面观察它们,我们会看到:
B
A
这和我看到的一样,但我们不是从正面看。正如@Scheff 在评论中指出的那样,我对 glm::lookat
的调用是将我的相机倒置并将其定位 "behind" 屏幕。
现在,如果您想象自己在显示器后面做倒立,A 和 B 现在看起来像这样:
∀
等等,但这不是我想要的吗 - 右下角的 B?
是的,但除了我的相机位置奇怪之外,我的 y 轴还因调用 glm::ortho
而翻转。通常 bottom
的值应小于 top
的值(如 this example)。
因此再次产生:
B
A
因此,一种解决方案是交换 glOrtho
中的 top
和 bottom
参数:
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, -1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, -1, 0) // up vector
);
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
-3.0f, // bottom (less than top -> y-axis is not inverted!)
3.0f); // top
如何翻转y轴"correctly"
上面的解决方案有效,但还有一个更简单的解决方案 - 或者至少更易于可视化!这只是将相机定位在场景前面并使用 glOrtho
翻转 y 轴(通过保持 bottom
大于 top
):
glm::mat4 view = glm::lookAt(
glm::vec3(0, 0, 1), // camera position
glm::vec3(0, 0, 0), // look at
glm::vec3(0, 1, 0) // up vector
);
glm::mat4 projection = glm::ortho(
-3.0f, // left
3.0f, // right
3.0f, // bottom (greater than top -> y-axis is inverted!)
-3.0f); // top
潜在问题
纹理方向
翻转 y 轴可能会导致纹理上下颠倒,这可以通过交换顶部和底部纹理坐标来解决。
背面剔除
如果启用 face culling,从不同角度查看场景可能会导致面孔被剔除。这可以通过更改顶点的缠绕顺序或通过更改 哪些 个面被剔除来解决。