我正在尝试了解我应该将相机位置放置在 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
这基本上就是 gluUnProject
或 glm::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/