我正在尝试使用C ++和openGL创建3D操作程序。我对openGL比较陌生,因此我经常不得不查找文档以找到合适的功能来完成我想要的事情。我以为我对正交投影和透视投影有了很好的了解(glOrtho
创建了一个正交投影,其中不同的z值看起来并不相同,glFrustum
创建了一个透视投影,其中z值是仔细看越大)。但是,当我在程序中换出glOrtho
和glFrustum
时,看不出任何区别。我在下面复制了一个显示效果的小程序。作为参考,我将openGL与freeglut一起使用。
#include "GL/freeglut.h"
void initFunc()
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glColor3f(1.0f, 1.0f, 0.0f);
glLineWidth(1.0f);
glutWireTeapot(0.3);
glTranslatef(0, -0.5, -0.5);
glutWireTeapot(0.3);
glutSwapBuffers();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Teapot Perspective");
initFunc();
glutDisplayFunc(displayFunc);
glutMainLoop();
}
我正在绘制两个茶壶,它们在y和z轴上都略有偏移。据我了解,glOrtho
应该使两个茶壶具有相同的位置,并且仅具有y偏移,而glFrustum
应该使其中一个比另一个大。但是,它们都使茶壶完全相同。
我在这里错过了什么吗?我还需要采取其他步骤来正确设置透视投影吗?还是我误解了glFrustum
的工作方式?我也尝试过使用gluPerspective
而不是glFrustum
,但是我似乎找不到合适的值来使用。我尝试使用FOV为90,纵横比为1以及各种z值的方法,但它们要么不生产茶壶,要么变形的茶壶无法识别。此外,gluPerspective
的行为似乎与带有相应参数的glFrustum
调用不同。我不确定我在这里缺少什么。
答案 0 :(得分:1)
在正交投影上,由于w
分量为1(对于笛卡尔输入坐标),视图空间中的坐标线性映射到剪辑空间坐标,并且剪辑空间坐标等于规范化的设备坐标。
左,右,下,上,近和远的值定义一个框。盒子体积内的所有几何图形在视口上都是“可见的”。
由glOrtho
定义的正交投影矩阵为:
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2/(r-l) 0 0 0
y: 0 2/(t-b) 0 0
z: 0 0 -2/(f-n) 0
t: -(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
在“透视投影”中,投影矩阵描述了从针孔相机中看到的世界3D点到视口的2D点的映射。
摄像机视锥台(截头金字塔)中的眼睛空间坐标映射到立方体(规范化的设备坐标)。
透视投影矩阵可以由平截头体(glFrustum
)定义。
距离left
,right
,bottom
和top
是指从视点中心到视锥面在近平面上的距离。 near
和far
指定了平截头体上到近平面和远平面的距离。
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2*n/(r-l) 0 0 0
y: 0 2*n/(t-b) 0 0
z: (r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
t: 0 0 -2*f*n/(f-n) 0
您提出这样的规范:
glFrustum(-1, 1, -1, 1, -1, 1);
没有定义适当的视锥,因为近平面的值为负,远平面的值为正。
如果要检查OpenGL错误(通过glGetError
),则将得到INVALID_OPERATION
错误。
void Frustum( double l, double r, double b, double t, double n, double f );
坐标(
l
b
−n
)T和(r
t
−n
)T指定近裁剪平面上的点分别映射到窗口的左下角和右上角(假设眼睛位于(0 0 0)T)。f
给出了从眼睛到远裁剪平面的距离。错误 如果
n <= 0
,f <= 0
,l == r
,b == t
或n == f
,则生成INVALID_VALUE错误。