c++ - 像素完美投影矩阵?

标签 c++ opengl matrix glm-math

我正在尝试了解我应该将相机位置放置在 lookat 函数(或模型矩阵中的对象)中多远,以便在顶点着色器中传递像素完美的坐标。

这对于正射投影矩阵来说实际上很简单,但我无法想象数学如何用于透视投影。

这是我正在使用的透视矩阵:

glm::mat4 projection = glm::perspective(45.0f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 10000.0f);

着色器中的顶点乘法非常简单:

gl_Position = projection * view * model * vec4(position.xy, 0.0f, 1.0);

我基本上是想在屏幕上显示一个需要旋转的四边形并显示透视效果(因此我不能使用正交投影),但我想在像素坐标中指定它的位置和大小应该出现在屏幕上。

最佳答案

好吧,如果您想使用梯形视锥,它只能在一个“z 平面”中有像素坐标。

基础数学

如果您使用标准相机,则 (0,0,0) 处相机的基本数学运算为

alpha 是垂直 fov(在你的例子中是 45°)

target_y = tan(alpha/2) * z 距离 * ((pixel_y/height)*2-1)
target_x = tan(alpha/2) * z-distance * ((pixel_x/width)*纵横比*2-1)

反向投影

至于一般情况。您可以“取消投影”以在所有变换结束于特定点之前找到 3D 中的某个点。

基本上,您需要取消计算。

gl_Position = projection * view * model * vec4(position.xy, 0.0f, 1.0);

因此,如果您有最终职位并想恢复它,您可以:

unprojection =  model^-1 * view^-1 *projection^-1 * gl_Position //not actual glsl notation, '^-1' being the inverse

这基本上就是 gluUnProjectglm::gtc::matrix_transform::unProject 等函数所做的。

但是你应该注意,应用投影矩阵后的最终裁剪空间通常是 [-1,-1,0] 到 [1,1,1],所以如果你想输入像素坐标,你可以应用转换到该空间的附加矩阵。

类似于:

               [2/width,        0,     0    -1]
               [      0, 2/height,     0    -1]
screenToClip = [      0,        0,     1     0]
               [      0,        0,     0     1]

会将 [0,0,0,1] 转换为 [-1,-1,0,1] 并将 [width,height,0,1] 转换为 [1,1,0,1]

此外,您最好尝试使用一些 z 值(例如 0.5),以确保您处于视锥体内并且不会在前部或后部附近剪裁。

关于c++ - 像素完美投影矩阵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34382798/

相关文章:

c++ - Valgrind 将此检测为可能的内存泄漏

c++ - 当我将构造函数声明为显式时出现编译错误

c++ - 显式初始化指针 vector 会导致转换错误?

matrix - Maxima:简化矩阵分量

c++ - 我可以使用 Eigen 稀疏矩阵来满足一般存储要求吗

matlab - 病态线性系统

C++ - 在覆盖期间调用析构函数时的类成员

java - 为什么 java 应用程序在 gdb 中崩溃但在现实生活中运行正常?

java.lang.NumberFormatException : empty string - OBJ Model Loader

python - 关于从 C++ 创建 Python 库的建议?