我试图理解 OpenGL MVP 矩阵,作为练习,我想使用矩阵绘制一个填充我的窗口的矩形。我以为我会很容易地找到一个教程,但我发现的所有这些似乎只是在他们的 MVP 矩阵设置中放置了随机值。
假设我的矩形有这些坐标:
GLfloat vertices[] = {
-1.0f, 1.0f, 0.0f, // Top-left
1.0f, 1.0f, 0.0f, // Top-right
1.0f, -1.0f, 0.0f, // Bottom-right
-1.0f, -1.0f, 0.0f, // Bottom-left
};
这是我的两个三角形:
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
如果我用身份 MVP 矩阵绘制矩形,它会按预期填充屏幕。现在我想使用平截头体。以下是它的设置:
float m_fov = 45.0f;
float m_width = 3840;
float m_height = 2160;
float m_zNear = 0.1f;
float m_zFar = 100.0f;
由此我可以计算窗口在 z-near 和 z-far 处的宽度/高度:
float zNearHeight = tan(m_fov) * m_zNear * 2;
float zNearWidth = zNearHeight * m_width / m_height;
float zFarHeight = tan(m_fov) * m_zFar * 2;
float zFarWidth = zFarHeight * m_width / m_height;
现在我可以创建我的 View 和投影矩阵:
glm::mat4 projectionMatrix = glm::perspective(glm::radians(m_fov), m_width / m_height, m_zNear, m_zFar);
glm::mat4 viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -m_zNear));
我现在希望这会使我的矩形填充窗口:
glm::mat4 identity = glm::mat4(1.0f);
glm::mat4 rectangleModelMatrix = glm::scale(identity, glm::vec3(zNearWidth, zNearHeight, 1));
但是这样做,我的矩形太大了。我错过了什么?
解决方案:正如@Rabbid76 指出的那样,问题在于计算我的 z-near 大小,它必须是:
float m_zNearHeight = tan(glm::radians(m_fov) / 2.0f) * m_zNear * 2.0f;
float m_zNearWidth = m_zNearHeight * m_width / m_height;
此外,我现在需要在规范化 View 空间 ([-0.5, 0.5]) 而不是设备空间 ([-1, 1]) 中指定我的对象坐标。因此我的顶点现在必须是:
GLfloat vertices[] = {
-0.5f, 0.5f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, // Bottom-right
-0.5f, -0.5f, 0.0f, // Bottom-left
};
最佳答案
物体在平行于 View xy 平面的平面上的投影高度为
h' = h * tan(m_fov / 2) / -z
在哪里
h
是平面上物体的高度,-z
是深度和 m_fov
是视场角。在你的情况下
m_fov
是 45° 和 -z
为 -0.1 ( -m_zNear
),因此 tan(m_fov / 2) / z
约为 4,142。由于四边形的高度为 2,因此四边形的投影高度约为 8,282。
要创建一个完全适合视口(viewport)的四边形,请使用 90° 的视野角和 1 的对象距离,因为
tan(90° / 2) / 1
是 1。例如:float m_fov = 90.0f;
glm::mat4 projectionMatrix = glm::perspective(glm::radians(m_fov), m_width / m_height, m_zNear, m_zFar);
glm::mat4 viewMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.0f));
如果
tan(m_fov / 2) == -z
,然后底部为 -1 顶部为 1 的对象适合视口(viewport)。因为被
z
划分,视口(viewport)上对象的投影尺寸随到相机的距离而线性减小。
关于c++ - OpenGL绘制一个矩形填充窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61251334/