OpenGL 的内置矩阵种种

news/2024/9/24 20:42:51/

文章目录

  • 一、说明
  • 二、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 的逆矩阵的转置”。现在你知道为什么了!


http://www.ppmy.cn/news/1454702.html

相关文章

RFC 791 (1)-导论

目录 浅论 IP是啥 IP可以管啥 操作 范例查看 提示&#xff1a;本系列将会开始RFC文档阅读&#xff0c;这里会给出我的一些笔记 浅论 我们这篇RFC文档描述的是IP和ICMP协议&#xff0c;我们都知道&#xff0c;在传统的OSI七层或者是现在被简化的五层&#xff1a;应用层&…

Docker 入门与实践:从零开始构建容器化应用环境

Docker 一、docker常用命令docker ps 格式化输出Linux设置命令别名 二、数据卷相关命令挂载到默认目录&#xff08;/var/lib/docker&#xff09;挂载到本地目录 三、自定义镜像Dockerfile构建镜像的命令 四、网络自定义网络 五、DockerCompose相关命令 一、docker常用命令 dock…

知识图谱实用网站推荐

​ 知识图谱是一种用于描述和组织的图形化表示方法&#xff0c;它是一种基于语义的知识表示方式&#xff0c;可以将各种实体、概念、属性以及关系等知识元素以图谱的形式进行展示和组织。 本文给大家分享了如何实现知识图谱中图关系的构建&#xff0c;以下是相关网站&#xff…

从新手到聊天专家:ChatGPT对话技巧全解析

关于为什么AI未能为你所用&#xff0c;许多人在拿到GPT后的首个问题便是&#xff1a;使用不佳。 这意味着&#xff0c;你可能会觉得ChatGPT的回答过于空洞&#xff0c;缺乏足够的参考价值。 其次&#xff0c;一个常见的问题是&#xff1a;不知如何利用。 即便拥有了GPT&#…

OpenHarmony实战开发-动画曲线、如何实现动画衔接

UI界面除了运行动画之外&#xff0c;还承载着与用户进行实时交互的功能。当用户行为根据意图变化发生改变时&#xff0c;UI界面应做到即时响应。例如用户在应用启动过程中&#xff0c;上滑退出&#xff0c;那么启动动画应该立即过渡到退出动画&#xff0c;而不应该等启动动画完…

Redis Cluster集群方案什么情况下会导致整个集群不可用?

Redis 没有使用哈希一致性算法&#xff0c;而是使用哈希槽。 Redis 中的哈希槽一共有16384个&#xff0c;计算给定 密钥的哈希槽&#xff0c;我们只需要对密钥的 CRC16 去取 16384。假设集群中有A、B、C三个集群节点&#xff0c; 不存在复制模式下&#xff0c;每个集群的节点包…

Edge扩展应用程序的上架流程

前言 在软件开发的生命周期中&#xff0c;发布流程是将产品推向市场并交付给用户的关键阶段。它不仅标志着一个项目从开发阶段到用户手中的转变&#xff0c;也是确保软件质量和用户体验的重要环节。那么一个清晰、高效且可重复的发布流程对于任何软件项目的成功至关重要&#…

pandas学习笔记13

map,apply,applymap ** apply&#xff1a;应用在DataFrame的行或列中&#xff1b; applymap&#xff1a;应用在DataFrame的每个元素中&#xff1b; map&#xff1a;应用在单独一列&#xff08;Series&#xff09;的每个元素中。** apply()方法 前面也说了apply方法是一般性的…