OpenGL 的内置矩阵种种

2024-05-03 10:04
文章标签 内置 矩阵 opengl 种种

本文主要是介绍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 的内置矩阵种种的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/956475

相关文章

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

Python 内置的一些数据结构

文章目录 1. 列表 (List)2. 元组 (Tuple)3. 字典 (Dictionary)4. 集合 (Set)5. 字符串 (String) Python 提供了几种内置的数据结构来存储和操作数据,每种都有其独特的特点和用途。下面是一些常用的数据结构及其简要说明: 1. 列表 (List) 列表是一种可变的有序集合,可以存放任意类型的数据。列表中的元素可以通过索

python内置模块datetime.time类详细介绍

​​​​​​​Python的datetime模块是一个强大的日期和时间处理库,它提供了多个类来处理日期和时间。主要包括几个功能类datetime.date、datetime.time、datetime.datetime、datetime.timedelta,datetime.timezone等。 ----------动动小手,非常感谢各位的点赞收藏和关注。----------- 使用datet

Linux内置的审计跟踪工具:last命令

如果你是一个服务器管理员,你或许知道你要保护你的服务器的话,不仅是从外部,还要从内部保护。Linux有一个内置工具来看到最后登陆服务器的用户,可以帮助你保护服务器。   这个命令是last。它对于追踪非常有用。让我们来看一下last可以为你做些什么。   last命令的功能是什么   last显示的是自/var/log/wtmp文件创建起所有登录(和登出)的用户。这个文件是二进制

线性代数|机器学习-P35距离矩阵和普鲁克问题

文章目录 1. 距离矩阵2. 正交普鲁克问题3. 实例说明 1. 距离矩阵 假设有三个点 x 1 , x 2 , x 3 x_1,x_2,x_3 x1​,x2​,x3​,三个点距离如下: ∣ ∣ x 1 − x 2 ∣ ∣ 2 = 1 , ∣ ∣ x 2 − x 3 ∣ ∣ 2 = 1 , ∣ ∣ x 1 − x 3 ∣ ∣ 2 = 6 \begin{equation} ||x

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接

OpenGL ES学习总结:基础知识简介

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库。 为桌面版本OpenGL 的一个子集。 OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工

OpenGL雾(fog)

使用fog步骤: 1. enable. glEnable(GL_FOG); // 使用雾气 2. 设置雾气颜色。glFogfv(GL_FOG_COLOR, fogColor); 3. 设置雾气的模式. glFogi(GL_FOG_MODE, GL_EXP); // 还可以选择GL_EXP2或GL_LINEAR 4. 设置雾的密度. glFogf(GL_FOG_DENSITY, 0

opengl纹理操作

我们在前一课中,学习了简单的像素操作,这意味着我们可以使用各种各样的BMP文件来丰富程序的显示效果,于是我们的OpenGL图形程序也不再像以前总是只显示几个多边形那样单调了。——但是这还不够。虽然我们可以将像素数据按照矩形进行缩小和放大,但是还不足以满足我们的要求。例如要将一幅世界地图绘制到一个球体表面,只使用glPixelZoom这样的函数来进行缩放显然是不够的。OpenGL纹理映射功能支持将