参考资料:
https://jsantell.com/3d-projection/
http://www.songho.ca/opengl/gl_projectionmatrix.html
说明:
投影矩阵用于投影变换,投影变换是三维场景中的物体正确渲染到二维屏幕的重要过程之一。在透视矩阵中,有几个重要元素:视场角、成像设备的宽高比、场景中能看到的最近距离以及最远距离,通过这几个参数可以定义一个视锥体对象,从而模拟人眼或者相机的在三维空间中的成像原理,通常有这个几个值就可以构造一个4x4的矩阵,通过OpenGL提供的接口设置即可。
上图是标准的OpenGL 透视投影矩阵,对于我们普通应用程序的视锥体是左右对称的,这样的话就存在以下几个等式:
r+l=0
t+b=0
r-l=2r=w
t-b=2t=h
所以我们更常见到的投影矩阵形式应该是这样的:
使用方式:
在实际开发场景中,我们可以利用现有的库生成矩阵,也可以利用透视投影的基础原理计算出矩阵。
这里列出前面提到的几个重要参数:
视场角:fov;
成像设备的宽高比:aspect;
近裁剪面距离:znear;
远裁剪面距离:zfar。
方式1:glFrustum
函数原型:
glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
计算方法:
示例代码:
glViewport(0, 0, args.width, args.height);
float tanx = tan(fov * 3.14159265f / 180.0f * 0.5f);
float top = args.znear * tanx;
float bottom = -top;
float right = top * (args.width / args.height);
float left = -right;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, bottom, top, args.znear, args.zfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
方式2:自己构造矩阵
构造方式:
参考上面的矩阵形式图,我们可以自己定义一个长度16的浮点数组,然后对应的填充对应下标的值,要注意的是OpenGL中投影矩阵是以列为主序的。
void xPerspective(float fov, float aspect, float znear, float zfar, float proj[16])
{
float fov_rad = fov * 3.14159265f / 180.0f;
float tan_fov = tan(fov_rad / 2);
proj[0] = 1.f / (tan_fov * aspect);
proj[1] = 0.0f;
proj[2] = 0.0f;
proj[3] = 0.0f;
proj[4] = 0.0f;
proj[5] = 1.f / tan_fov;
proj[6] = 0.0f;
proj[7] = 0.0f;
proj[8] = 0.0f;
proj[9] = 0.0f;
proj[10] = (-zfar - znear) / (zfar - znear);
proj[11] = -1.0f;
proj[12] = 0.0f;
proj[13] = 0.0f;
proj[14] = -2.0f * zfar * znear / (zfar - znear);
proj[15] = 0.0f;
}
示例代码:
float proj[16] = { 0 };
xPerspective(args.fovy, args.width/args.height, args.znear, args.zfar, proj);
glViewport(0, 0, args.width, args.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glLoadMatrixf(proj);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
方式3:使用第三方库
直接利用glu或者glm提供的函数,把fov、aspect、znear、zfar这几个参数传入即可。
glu函数原型:
void APIENTRY gluPerspective (
GLdouble fovy,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar);
glu代码示例:
glViewport(0, 0, args.width, args.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(args.fovy, args.width/args.height, args.znear, args.zfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glm函数原型:
template
GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> perspective
(
T const & fovy,
T const & aspect,
T const & zNear,
T const & zFar
)文章来源:https://www.toymoban.com/news/detail-432067.html
glm代码示例:文章来源地址https://www.toymoban.com/news/detail-432067.html
glm::mat4 proj = glm::perspective(args.fovy, args.width / args.height, args.znear, args.zfar);
glViewport(0, 0, args.width, args.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glLoadMatrixf(glm::value_ptr(proj));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
到了这里,关于【OpenGL-矩阵】投影矩阵(ProjectionMatrix)理解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!