OpenGL里的矩阵堆栈(MVP的初始化以及后续更改M,V,P的操作)

OpenGL矩阵堆栈

是OpenGL用于进行矩阵变换的一种机制,它包括模型视图矩阵堆栈和投影矩阵堆栈两种类型的矩阵堆栈。每个矩阵堆栈都可以通过调用glMatrixMode函数来进行切换。一旦切换到某个矩阵堆栈,所有的矩阵操作都会作用于该矩阵堆栈。

M模型矩阵:模型矩阵(Model Matrix)用于描述物体在世界坐标系中的位置、方向和大小等属性。通过对模型矩阵进行变换,可以实现物体的平移、旋转和缩放等效果。

glTranslatef:对模型矩阵进行平移变换;
glRotatef:对模型矩阵进行旋转变换;
glScalef:对模型矩阵进行缩放变换。
这些函数可以将变换矩阵乘以当前的模型矩阵,从而实现对模型矩阵的变换。例如,通过调用glTranslatef(x, y, z)函数,可以将模型矩阵右乘一个平移矩阵,实现对模型的平移变换。同样的道理,通过调用glRotatef(angle, x, y, z)函数,可以将模型矩阵右乘一个旋转矩阵,实现对模型的旋转变换;通过调用glScalef(sx, sy, sz)函数,可以将模型矩阵右乘一个缩放矩阵,实现对模型的缩放变换。
除了上述函数之外,我们还可以通过调用glLoadMatrixf函数或glMultMatrixf函数,直接加载或乘以一个指定的变换矩阵,来对模型矩阵进行变换。通过这些函数的组合,我们可以实现复杂的模型变换,从而创建出各种形态的3D场景。

V视图矩阵:视图矩阵(View Matrix)用于描述摄像机在世界坐标系中的位置和方向等属性。通过对视图矩阵进行变换,可以实现摄像机的移动、旋转和缩放等效果。

gluLookAt:对视图矩阵进行相机变换,即描述摄像机在场景中的位置、方向和朝向。
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz);
eyeX, eyeY, eyeZ:摄像机的位置坐标;
centerX, centerY, centerZ:摄像机的观察点坐标,即相机所看向的点;
upX, upY, upZ:相机的上方向向量,用于确定相机的朝向。

通过调用gluLookAt函数,我们可以实现对视图矩阵的变换,从而实现对场景的观察和渲染。除了gluLookAt函数之外,我们还可以通过调用glTranslatef、glRotatef和glScalef(平移旋转缩放)等函数,对视图矩阵进行变换。这些函数同样是将变换矩阵右乘到当前的视图矩阵中,从而实现对视图矩阵的变换。
(在OpenGL中,视图矩阵是描述摄像机在世界坐标系中的位置和方向等属性,而不是描述物体在摄像机坐标系中的位置和方向等属性。)

P透视矩阵:投影矩阵(Projection Matrix)用于描述将3D场景投影到2D平面的方式和参数。通过对投影矩阵进行变换,可以实现对场景的投影和呈现。

glFrustum:定义一个透视投影矩阵,使得视景体内的物体根据距离大小有不同的大小;
glOrtho:定义一个正交投影矩阵,使得视景体内的物体大小不会因为距离的远近而有所变化;
gluPerspective:定义一个透视投影矩阵,用于指定视景体内部的各个物体在投影平面上的大小和位置。
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
第一个参数fovy表示视角(Field of View,FOV),用于指定视场的大小,单位是度(degree);第二个参数aspect表示宽高比(Aspect Ratio),用于指定视图的宽高比,即视口的宽度与高度之比;第三个参数zNear表示近裁剪面(Near Clipping Plane),用于指定从摄像机到近裁剪面的距离;第四个参数zFar表示远裁剪面(Far Clipping Plane),用于指定从摄像机到远裁剪面的距离。
除了上述函数之外,我们还可以通过调用glLoadMatrixf函数或glMultMatrixf函数,直接加载或乘以一个指定的变换矩阵,来对投影矩阵进行变换。通过这些函数的组合,我们可以实现复杂的投影变换,从而创建出各种形态的3D场景。

这三个矩阵在opengl中的初始化以及后续操作顺序

在OpenGL中,通常的矩阵堆栈操作顺序为先对投影矩阵(P矩阵)进行初始化和操作,再对视图矩阵(V矩阵)进行初始化和操作,最后对模型矩阵(M矩阵)进行初始化和操作。
(1)通过glMatrixMode(GL_PROJECTION)设置当前矩阵模式为投影矩阵模式,并通过glLoadIdentity()清空投影矩阵堆栈,以便进行后续操作。
(2)通过gluPerspective()等函数设置投影矩阵的具体参数,如视角、宽高比、近裁剪面和远裁剪面等。
(3)通过glMatrixMode(GL_MODELVIEW)设置当前矩阵模式为视图矩阵模式,并通过glLoadIdentity()清空视图矩阵堆栈,以便进行后续操作。
(4)通过gluLookAt()等函数设置视图矩阵的具体参数,如摄像机的位置、观察点和上方向向量等。
(5)通过对模型矩阵进行平移、旋转、缩放等变换操作,对场景进行模型变换。这些操作通过对模型矩阵堆栈的操作实现。
(6)最后,通过将投影矩阵、视图矩阵和模型矩阵依次相乘的方式,得到最终的变换矩阵,并将其传递给渲染管线进行处理和渲染。
需要注意的是,OpenGL的矩阵堆栈操作遵循右乘的顺序,即先进行的变换操作会先被应用。因此,在对模型矩阵进行操作时,需要注意操作顺序,以确保得到正确的渲染结果。

在我们渲染中更改M,V,P的话

在OpenGL中,每次更改M、V或P矩阵时,并不需要完整地重新走一遍设置矩阵的流程,而只需要在相应的矩阵堆栈中压入或弹出一个新的矩阵,或者通过矩阵乘法等操作对已有的矩阵进行修改。
具体来说,当需要更改M、V或P矩阵时,可以通过glMatrixMode()函数将当前的矩阵模式切换到相应的模式(如GL_MODELVIEW或GL_PROJECTION),并通过glPushMatrix()或glPopMatrix()函数压入或弹出一个新的矩阵,或者通过glLoadMatrix()或glMultMatrix()等函数直接修改已有的矩阵。
例如,当需要更改模型矩阵M时,可以通过以下步骤完成:
(1)通过glMatrixMode(GL_MODELVIEW)将当前的矩阵模式切换到模型视图矩阵模式。
(2)通过glPushMatrix()函数将当前的模型矩阵压入堆栈中,以便后续操作。
(3)通过glTranslatef()、glRotatef()、glScalef()等函数对模型矩阵进行变换操作。
(4)通过glPopMatrix()函数弹出新的模型矩阵,并将其与视图矩阵和投影矩阵相乘,得到最终的变换矩阵,传递给渲染管线进行处理和渲染。
当需要修改视图矩阵V时,可以通过以下步骤完成:
(1)通过glMatrixMode(GL_MODELVIEW)将当前的矩阵模式切换到模型视图矩阵模式。
(2)通过glLoadIdentity()函数将当前的视图矩阵堆栈清空,以便进行后续操作。
(3)通过gluLookAt()函数设置新的视图矩阵参数,如摄像机的位置、观察点和上方向向量等。
(4)将新的视图矩阵压入堆栈中,以便后续渲染操作。
(5)将投影矩阵、视图矩阵和模型矩阵依次相乘,得到最终的变换矩阵,并将其传递给渲染管线进行处理和渲染。
需要注意的是,在修改视图矩阵时,需要将当前的视图矩阵堆栈清空,以便进行新的操作。如果不清空堆栈,会导致新的视图矩阵和旧的视图矩阵相乘,从而产生错误的变换效果。
注释:在修改视图矩阵V时,模型矩阵M中的变换操作是不会受到影响的,这些变换操作会一直保留下来,直到再次对模型矩阵进行修改。这是因为视图矩阵V和模型矩阵M是两个独立的矩阵,它们分别对应着场景中的视角和物体的位置、旋转、缩放等变换操作。
当需要修改投影矩阵P时,可以按照以下步骤进行操作:
(1)将矩阵模式切换为投影矩阵模式:glMatrixMode(GL_PROJECTION)
(2)将堆栈清空:glLoadIdentity()
(3)根据具体需求设置新的投影矩阵P,例如使用gluPerspective()函数设置透视投影矩阵:gluPerspective(fovy, aspect, zNear, zFar)
(4)将新的投影矩阵P加载到当前矩阵堆栈的顶部:glLoadMatrixf§

修改MVP都是独立的操作,分别对应着模型坐标系、观察坐标系和投影坐标系的变换。因为每个坐标系的变换方式和需求不同,所以这三个矩阵是相互独立的,修改一个矩阵不会影响到其他矩阵。
在渲染过程中,**首先根据模型矩阵M将顶点从模型坐标系变换到世界坐标系,然后根据视图矩阵V将顶点从世界坐标系变换到观察坐标系,最后根据投影矩阵P将顶点从观察坐标系变换到裁剪坐标系,并进行透视或正交投影。**这些变换都是独立的,每个矩阵都承担着自己的角色。

(在OpenGL之外,一般采用左乘的方式进行矩阵变换。左乘的方式指的是先将变换矩阵乘以当前矩阵,再将乘积矩阵作为当前矩阵。左乘的方式适用于行向量,可以看作是在左边乘以变换矩阵。
相比之下,OpenGL中使用的右乘方式适用于列向量,可以看作是在右边乘以变换矩阵。右乘的方式可以将矩阵乘法表示为矩阵乘向量的形式,便于在渲染管线中进行优化。
因此,在OpenGL之外,如果需要进行矩阵变换,一般采用左乘的方式进行,而在OpenGL中,采用右乘的方式进行矩阵变换。需要注意的是,如果将左乘的方式应用于OpenGL中,可能会导致渲染结果出现错误。)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值