c++ - OpenGL绘制一个矩形填充窗口

标签 c++ opengl projection glm-math frustum

我试图理解 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/

相关文章:

c++ - 如何在图像上绘制模糊矩形?

C++ 命令行界面

opengl - 定义指向 OpenGL 顶点数组对象的指针

opengl - GLSL float/vec3/vec4 数组最大大小 = GL_MAX_VERTEX_UNIFORM_VECTORS?

graphics - 将 y 剪切地平线偏移转换为光线转换器中的俯仰角

C++ - 如何在不重载比较运算符的情况下为 std::max 专门化自定义类型?

python - 如何通过 Python/C API 将 Python 实例传递给 C++

java - 使用 lwjgl 让背景闪烁

c - openGL 数学书,用于学习矩阵旋转/投影平截头体设置等

c# - Entity Framework 6.1.3 : Projection - load children of children directly