虽然我是opengl的新手,并且勉强寻求帮助,但我认为需要对Z轴,深度测试和GLM:ortho进行一些澄清。 与此争吵了一两个星期,一切都从一开始就“逆转”了。
所以即时使用:
glDepthFunc(GL_LESS);
glDepthRange(0.0f, 1.0f);
glm::ortho(0.0f, 800, 0.0f, 800), 0.0f, 1.0f);
根据这个thread和glDepthFunc / glClearDepth的默认值,当MVP被提供给着色器时,一切都应该在左手坐标中。
因此,当我读到链接的线程时,我发现glm :: ortho应该将右手坐标(因为这显然是每个人在示例中使用的东西)转换为左手坐标。听起来不错,为什么它不起作用?
当你查看GLM库时,你会发现glm :: ortho,glm :: orthoLH和glm :: orthoRH听起来非常苛刻。如果我使用glm :: orthoLH,一切都会加起来并且完美无缺,因为它将我的所有坐标转换为左手坐标。那么为什么glm :: ortho不能为我做这个呢?
编译GLM库时,显然有一个设置。当调用glm :: ortho时,GLM_COORDINATE_SYSTEM控制系统是否将默认使用glm :: orthoLH或glm :: orthoRH。令我惊讶的是,glm :: orthoLH不是默认值。
如果你查看GLM的源代码,你会发现这些行,
#define GLM_LEFT_HANDED 0x00000001 // For DirectX, Metal, Vulkan
#define GLM_RIGHT_HANDED 0x00000002 // For OpenGL, default in GLM
#ifdef GLM_FORCE_LEFT_HANDED
# define GLM_COORDINATE_SYSTEM GLM_LEFT_HANDED
#else
# define GLM_COORDINATE_SYSTEM GLM_RIGHT_HANDED
#endif
OpenGL是右撇子,不需要将ortho转换成左手?
所以我的问题是,
如果这没有任何意义,请纠正我。我也很困惑:))
答案 0 :(得分:2)
我认为你的主要困惑与这个问题有关:
为什么GLM认为OpenGL是右撇子?
OpenGL不是右撇子,也不是左撇子。 OpenGL只是一个渲染API,而不是一个坐标系。
在典型的渲染管道中,您确实有许多不同的坐标系,例如:
这些坐标系中的每一个都可以拥有自己的惯例,包括它自己的惯用手法。
具有固定功能管道和集成矩阵堆栈的旧版OpenGL考虑了一些坐标约定(但它并未完全强制您使用这些约定)。
如此经典的OpenGL约定是:
标准化的设备空间/窗口空间左手,x指向右侧,y向上,z指向屏幕,右侧用x向右,y向上,摄像机指向-z方向。对象和世界空间通常也是右手(因此视图转换只是旋转+平移,没有镜像)。
在投影矩阵中完成了手性的翻转。传统GL的其他一些惯例是,近和远剪裁平面位置始终被定义为到观察方向的距离,因此glOrtho(..., 2,5)
确实设置了映射{{1}的变换{}} z_eye=-2
和z_ndc=-1
z_eye=-5
。
如果你看看我写的映射,它应该解释这个问题:
Okej,所以一切都应该加起来,小Z在前面,后面是大,但没有。一切都是相反的。
如你所见,“小”z(-5)在后面,“大”z(-2)在前面,就像它应该在右手坐标系中一样。
当 NOT 设置z_ndc=1
时,glm使用与旧版GL相同的约定。它将通过在proejction矩阵中翻转z来建立右手视图空间(并假设所有后面的空间NDC和窗口空间都配置为左手)。
如果您设置了GLM_FORCE_LEFT_HANDED
,它将不会沿z引入镜像,但仍会将GLM_FORCE_LEFT_HANDED
和near
视为距观看方向的距离,现在为{{1 }}。这将产生建立左手视图空间的结果(只要NDC和Window空间也设置为左手)。
在处理着色器时,OpenGL是否真的需要右手使用MVP?
这些都是公约。你必须以某种方式决定它们,没有人比其他人更好。如果你有不同的部分或部分使用不同的约定,这些东西只会变得有趣(而且很烦人),你必须非常小心地在正确的位置正确地转换数据。