本文主要是介绍OpenGL 的内置矩阵种种,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 一、说明
- 二、glMatrixMode的三个选项
- 三、OpenGL 矩阵操作
- 四、入栈和弹出矩阵
- 五、设置内置 OpenGL 矩阵
- 六、矩阵设置异端
- 七、正常矩阵
一、说明
内置 OpenGL有几个重要矩阵,围绕这几个矩阵,OpenGL 有一小组 矩阵操作。在本例中为 glMatrixMode,这是非常有用的例程。
二、glMatrixMode的三个选项
实际上,只有三件事可以传递给 glMatrixMode:
- glMatrixMode(GL_MODELVIEW);是常见的情况。 这使得所有后续矩阵操作都会影响 “gl_ModelViewMatrix”,主要用于模型设置(用于 例如,缩小汽车模型以适合建筑模型旁边)。
- glMatrixMode(GL_PROJECTION);切换到 投影矩阵,“gl_ProjectionMatrix”。投影矩阵的 工作平时是进行透视分割,但实际上我经常 将其用于整个相机变换;基本上是 ViewProjection 而不仅仅是投影。
- glMatrixMode(GL_TEXTURE);切换到纹理 矩阵。这可用于调整纹理坐标 传入。使用可编程硬件,通常更容易 自己调整gl_MultiTexCoord0。
固定功能硬件实质上在每个顶点上执行以下 GLSL 代码:
其他一切实际上只是约定俗成的问题。
gl_Position = gl_ProjectionMatrixgl_ModelViewMatrixgl_Vertex;
三、OpenGL 矩阵操作
OpenGL 有一大堆有用的实用程序例程,它们作用于当前矩阵(由 glMatrixMode 设置):
- glLoadIdentity();清除当前矩阵,将其替换为恒等式,如“M=mat4(1.0);”。
- glMultMatrixf(&newMat[0][0]);将当前矩阵乘以新的列矩阵,将“M”替换为“M*newMat”。适用于 C++ mat4 对象。
- glTranslatef(dx,dy,dz); 移动当前坐标系的原点。
- glScalef(sx,sy,sz);缩放当前坐标系。按大值扩展 让东西变大。您还可以通过缩放 负值。
- glRotatef(ang,x,y,z);围绕向量 x,y,z 右旋 ang 度旋转。为 例如,glRotatef(45.0,0,0,1);将屏幕上的内容旋转 45 度逆时针方向。
还有很多其他的例程。您还可以提取矩阵值并根据需要手动操作它们:
mat4 p; /* stores the Projection matrix */
glGetFloatv(GL_PROJECTION_MATRIX,&p[0][0]); /* read back the projection matrix */
mat4 t=mat4(1.0); /* soon to be a Translation matrix */
t[3].z += dz; /* set translation offset */
p=p*t; /* multiply projection matrix by translation matrix */
glLoadMatrixf(&p[0][0]); /* copy new matrix into OpenGL */
四、入栈和弹出矩阵
OpenGL 矩阵最酷的地方是推送和弹出。 比方说,要画出你世界的一小块,你需要翻译 并缩放坐标系。然后画一些其他的棋子, 您需要返回原始坐标系,并进行平移 并以不同的方式扩展。OpenGL 使用 glPushMatrix 使这一切变得简单 和 glPopMatrix,它将当前矩阵保存到一点 OpenGL 内部堆栈。
在这段代码之后,矩阵保持不变。没有 推送和弹出,您将被 model1.origin + model2.origin 翻译。
glPushMatrix(); /* save old coordinate system */
glTranslatef(model1.origin.x,model1.origin.y,model1.origin.z);
model1.draw();
glPopMatrix(); /* restore old coordinate system */
五、设置内置 OpenGL 矩阵
初始化内置 OpenGL 矩阵的常用方法是使用 每帧开头的一小段代码,在“显示”中 常规。你至少要建立透视分界线 和相机方向。我的矩阵设置代码通常如下所示 this:
以每个 MatrixMode 的 glLoadIdentity 开始每一帧非常重要,因为:
// Load all needed matrices into OpenGL:
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); /*<- clean out any old leftover matrices */
gluPerspective(90.0, /* <- Y camera field-of-view, in degrees */win_w/(float)win_h, /* viewport's aspect ratio: always width over height */0.01, /* Near clipping plane depth */100.0 /* Far clipping plane depth */
);
/* if you're not Dr. Lawlor, you'd switch to GL_MODELVIEW here */
glTranslatef(0,0,-2.0); /* push world origin down the *unrotated* Z axis */
glMultMatrixf(&viewMat[0][0]); /* camera orientation: can also go under GL_MODELVIEW */glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
OpenGL 不会在每一帧之后重置矩阵,因此很容易得到可怕的奇怪矩阵,在那里你一遍又一遍地进行透视划分。(试试这个!太可怕了!
MPIglut(我们将在 2 月份讨论)覆盖 glLoadIdentity 以添加其子窗口矩阵。
六、矩阵设置异端
有些人喜欢将GL_PROJECTION设置放在重塑中 常规。这是一个坏主意,因为某些版本的 GLUT 没有 调用 Reshape 例程,直到窗口实际重塑。 此外,这使得动画制作变得更加棘手,例如相机 视场。
其他人更喜欢只把视角鸿沟放在 GL_PROJECTION矩阵。此方法适用于固定函数 硬件的(丑陋得可怕)每个顶点照明,用于镜面反射 照明假设后GL_MODELVIEW摄像机位于原点 (固定功能照明发生在眼睛空间中)。同样,使用 可编程着色器,你可以做任何你喜欢的事情——我喜欢做 世界空间中的照明,如果整个相机最容易 转换在GL_PROJECTION矩阵中。
所以我有点像矩阵异端——我对待GL_MODELVIEW和 GL_PROJECTION就像他们实际上是GL_MODEL和 GL_VIEWPROJECTION。这意味着我的矩阵不适用于 固定功能 OpenGL 镜面光源,使用起来既笨重又 丑。由于我更喜欢每像素镜面反射照明,所以我不喜欢 请注意这一点。
七、正常矩阵
普通人很有趣。它们是 vec3 的,因为你不想要 对法线的看法。而且它们实际上并没有完全扩展 右图 - 具有 45 度法线的 45 度曲面,由 glScalef(1,0.1,1) 将曲面降低到接近 0 度,但 实际上将法线向上倾斜,方向与 表面,接近 90 度。
从数学上讲,如果在表面上的两点 a 和 b 之间, dot(n,b-a)==0,则在将矩阵 M 应用于点后,您需要 法线仍然是垂直的。问题是,什么 矩阵 N 您是否必须应用于法线才能实现这一点? 换句话说,找到 N 使得
dot( N * n , M * a - M * b) == 0
我们可以通过注意到点积可以表示为矩阵来解决这个问题 乘法–dot(x,y) = transpose(x) * y,其中我们处理一个普通的 column-vector 作为一个小矩阵,并水平翻转它。所以
transpose(N * n) * (M*a - M*b) == 0 (as above, but write using transpose and matrix multiplication)transpose(N * n) * M * (a-b) == 0 (collect both copies of M)transpose(n) * transpose(N) * M * (a-b) == 0 (transpose-of-product is product-of-transposes in opposite order)
好的。这确实类似于我们假设原始法线垂直于表面——即:
dot(n,b-a) == transpose(n) * (a-b) == 0
事实上,唯一的区别是楔入中间的新矩阵。如果我们选择 N 使中间的项成为恒等式,那么我们的新法线也将垂直于表面:
transpose(N) * M == I (the identity matrix)
这是矩阵逆矩阵的定义,因此“正常矩阵”
N = transpose(inverse(M)).
如果您查找“gl_NormalMatrix”的 GLSL 定义,它被定义为“gl_ModelViewMatrix 的逆矩阵的转置”。现在你知道为什么了!
这篇关于OpenGL 的内置矩阵种种的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!