一篇搞懂数学在OpenGL中的应用及矩阵

这篇具有很好参考价值的文章主要介绍了一篇搞懂数学在OpenGL中的应用及矩阵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、图形学中的矩阵

1.矩阵的计算公式

2.矩阵变换

3.为什么旋转,平移都是左乘矩阵,不能右乘

4.齐次坐标系统

5.变换先后顺序

二、利用矩阵来变换图形

(补充)

三、OpenGL中的三种变换矩阵



 话不多说,我把我看的视频链接贴出来,下面的笔记是由视频学习和自己的补充而来。这次是(19-20)的笔记

跟着这个小哥的教学视频学的(YouTube原视频,科学上网AI字幕) ►               http://bit.ly/2lt7ccM
这个是哔哩哔哩网站有人搬运的 ►最好的OpenGL教程之一_哔哩哔哩_bilibili

其实在OpenGL使用中大部分并不特别涉及你需要自己手动去算那么复杂的线性变换,我们先了解一下线性代数的矩阵内容,然后我们再回到代码看看,OpenGL中的投影用到的矩阵的原因和效果

一、图形学中的矩阵

1.矩阵的计算公式

矩阵是一个按照长方阵列排列的数学对象,它在线性代数和其他数学领域中有广泛的应用。以下是一些基本的矩阵计算公式:

1.  矩阵加法:

•   如果两个矩阵 A 和 B的维度相同(即行数和列数相同),它们可以相加。结果矩阵 C 的每个元素等于 A 和 B对应位置的元素之和。 C=A+B

2.  矩阵减法:

•   如果两个矩阵 A 和 B 的维度相同,它们可以相减。结果矩阵 C 的每个元素等于 A 对应位置的元素减去 B 对应位置的元素。 C=A−B

3.  矩阵乘法:

•   如果矩阵 A 的列数等于矩阵 B 的行数,它们可以相乘。结果矩阵 C 的每个元素是 A 的行与 B 的列对应元素的乘积之和。 Cij=∑k=1nAik⋅Bkj

•   这个计算可以用矩阵乘法的运算符表示为 C=AB。

4.  矩阵转置:

•   矩阵的转置是将矩阵的行和列交换得到的新矩阵。如果 A 是一个 m×n 的矩阵,其转置 AT 是一个 n×m 的矩阵,其中 AijT=Aji。

5.  标量与矩阵的乘法:

•   一个标量(常数)可以与一个矩阵的每个元素相乘。如果 c 是一个标量,A 是一个矩阵,那么 cA 的每个元素等于 c 乘以 A 对应位置的元素。

这些是矩阵的基本运算。矩阵在线性代数、图形学、物理学等领域中都有广泛的应用。

2.矩阵变换

让我们通过几个具体的例子来说明不同矩阵变换的计算和实际效果:

1. 平移矩阵:

矩阵计算:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

其中 tx 和 ty 是平移的水平和垂直距离。

实际效果: 假设有一个二维点 P(x,y),应用平移矩阵后,新的点 P′(x′,y′) 的坐标为:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

2. 缩放矩阵:

矩阵计算:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

其中 sx 和 sy 是水平和垂直方向上的缩放因子。

实际效果: 应用缩放矩阵后,二维点 P(x,y) 的新坐标为:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

3. 旋转矩阵:

矩阵计算(绕原点旋转):

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

其中 θ 是旋转角度。

实际效果: 应用旋转矩阵后,二维点 P(x,y) 的新坐标为:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

这些例子说明了矩阵计算如何实现平移、缩放和旋转的图形变换。通过将这些变换组合使用,可以创建更复杂的图形效果。在实际应用中,这些变换通常用于构建三维图形的模型视图、投影视图等。

3.为什么旋转,平移都是左乘矩阵,不能右乘

在图形学和计算机图形学中,矩阵乘法的选择通常是基于向量乘法的约定和坐标系统的定义。对于二维和三维图形变换,我们使用齐次坐标系统和矩阵乘法来表示平移、旋转等变换。

齐次坐标系统和矩阵乘法

在齐次坐标系统中,我们使用四维向量来表示三维空间中的点。一个三维点 (x,y,z) 可以表示为四维向量 (x,y,z,1)。这样的表示允许我们使用四维矩阵来表示平移、旋转等变换。

在二维情况下,我们使用三维向量表示二维点,同样使用四维矩阵表示变换。

为什么是左乘矩阵?

矩阵与向量的顺序: 在图形学中,我们通常使用列向量来表示点,这就意味着我们将矩阵放在左边(左乘矩阵)。

复合变换的顺序: 当我们对一个点进行多次变换时,这些变换是按照从右到左的顺序应用的,因此我们使用左乘矩阵来表示这个复合变换。

变换链的可读性: 采用左乘矩阵的方式可以更自然地表示变换的链式结构。例如,如果有一个平移矩阵 T 和一个旋转矩阵 R,则复合变换 R⋅T 表示先平移后旋转。

具体例子

考虑一个平移矩阵 T 和一个旋转矩阵 R,以及一个二维点 (x,y)。对于平移,我们希望点在平移后变成 (x+tx,y+ty)。对于旋转,我们希望点在旋转后变成 (x′,y′)。

如果我们使用左乘矩阵的形式:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

其中,tx 和 ty 是平移的水平和垂直距离,θ 是旋转角度。

这种表示方式使得复合变换的应用更为自然。因此,左乘矩阵的选择更符合图形学中的表示约定和变换的顺序。

4.齐次坐标系统

在齐次坐标系统中,四维向量通常表示三维空间中的点或向量,并且有一个额外的第四个分量。这个额外的分量通常是 w,有时也称为齐次坐标。在齐次坐标系统中,四维向量表示为 (x,y,z,w)。

1. 点的表示:

对于一个三维点 (x,y,z),在齐次坐标中表示为 (x,y,z,1)。

这里的 w 常常设置为 1,表示点的齐次坐标。

2. 向量的表示:

对于一个三维向量 (x,y,z),在齐次坐标中同样表示为 (x,y,z,0)。

这里的 w 常常设置为 0,表示向量的齐次坐标。

3. 齐次坐标和矩阵变换:

在矩阵变换中,我们使用四维矩阵来表示平移、旋转等变换。

齐次坐标的引入使得矩阵变换可以统一表示为一个 4×4 的矩阵。

齐次坐标的 w 分量在矩阵变换中用来确保在变换后的坐标系统中正确表示点的位置。

4. 投影:

在透视投影中,齐次坐标的 w 分量用来表示深度信息。

在投影变换中, w 分量的值可以影响到投影的效果,从而实现透视效果。

总结:

齐次坐标中的第四个分量 w 在不同的场景下有不同的含义,但总的来说,它可以用来扩展三维向量和点的表示,使得矩阵变换可以更加灵活地应用于图形学和计算机图形学中的各种操作。

5.变换先后顺序

在图形学中,矩阵的乘法顺序非常重要,它决定了变换的顺序。一般来说,在矩阵乘法中,右乘的矩阵先作用于向量。考虑平移矩阵 T 和旋转矩阵 R,我们可以详细解释它们的作用顺序。

1. 先平移后旋转的顺序(右乘矩阵):

假设有一个二维点 P(x,y)。先应用平移矩阵 T,再应用旋转矩阵 R,得到新的坐标 P′。表示为:

P′=R⋅T⋅P

其中,

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

具体的计算过程为:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

2. 先旋转后平移的顺序(左乘矩阵):

如果我们希望先旋转后平移,即先应用旋转矩阵 R,再应用平移矩阵 T,那么表示为:

P′=T⋅R⋅P

这时,平移矩阵 T 放在左边,旋转矩阵 R 放在右边。具体的计算过程为:

一篇搞懂数学在OpenGL中的应用及矩阵,OpenGL,矩阵,算法,图形渲染,c++,线性代数

选择哪种顺序取决于具体需求:如果先平移再旋转,对象会绕着自身中心旋转。如果先旋转再平移,对象会绕着全局坐标系的原点旋转后再平移。在实际应用中,选择哪种顺序取决于你希望的变换效果。

二、利用矩阵来变换图形

有些走远了,所以我们还是进入正题,在OpenGL代码中如何进行变换,接下来我们就以正交矩阵来进行变换吧。

1.引入glm数学库,主要是矩阵的库就行:

https://github.com/g-truc/glm/releases/tag/0.9.9.8

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

2.声明一个矩阵 正交矩阵

glm::mat4 proj = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);

3.在着色器类中声明设置矩阵函数

void Shader::SetUniformMat4f(const std::string& name, const glm::mat4& matrix)
{
    //location 指定要修改的统一变量的位置。
    //count 对于vector(glUniform*v)命令,指定要修改的元素数。如果目标统一变量不是数组,则应为1;如果是数组,则为1或更大。
    // 对于matrix(glUniformMatrix*)命令,指定要修改的矩阵数。如果目标一致变量不是矩阵数组,则该值应为1;如果是矩阵数组,应为1或更大。
    //transpose 对于矩阵命令,指定在值加载到统一变量中时是否转置矩阵。
    // v0、v1、v2、v3
    //对于标量命令,指定要用于指定统一变量的新值。
    //value 对于矢量和矩阵命令,指定一个指向计数值数组的指针,该数组将用于更新指定的统一变量。
    //&matrix[0][0]就是把 glm::mat4&转化为数组储存,并引用指针
    GLCall(glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &matrix[0][0]));
}

4.着色器代码、其中u_MVP就是我们的投影矩阵

#shader vertex
#version 330 core

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord;

out vec2 v_TexCoord;

//模型视觉投影矩阵
uniform mat4 u_MVP;

void main()
{
    //利用正交矩阵把图形的顶点变形到想要的位置上去
    gl_Position = u_MVP * position;
    v_TexCoord = texCoord;
};

5.可以看到我们实际上是用了gl_Position = u_MVP * position;上面数学公式提到的一些矩阵变换数学运算,只不过不是我们去算,意思就是这样去变换

shader.SetUniformMat4f("u_MVP", proj);

就是这样我们完成了在OpenGL中利用矩阵这样的数学高大上的东西,变换了坐标,而且其实很多复杂的变化也是这样来实现的, 其实学过线性代数的应该都知道,这就是线性代数有魅力的地方,就好像魔方一样,通过许多的变换矩阵来完成到你想要的那个展现矩阵上去,帮助我们在OpenGL上完成了对2D矩阵的显示变换。

而我们知道,投影其实也是差不多的意思,当在2D游戏中,就像我们刚刚上面所做的,用一个正交矩阵来完成等比例的放大缩小,而让整个游戏的比例不变,当一个3D的物体要在2D屏幕上显示,还要拥有着3D的视觉,也就是近大远小,就必须有投影的概念,经典的就有正交投影和透视投影两种投影矩阵,无意外就是通过矩阵来实现变换的。

也就是我们可以变化glm::mat4 proj = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);中的这些值,,也可以变换顶点坐标中的值,因为最后渲染器都是会通过数学矩阵变化,把这些顶点值转换为一个个在-1到1间的值,比如最后值在0.25,就是在屏幕中心往右1/4的位置,这就是标准统一坐标系的引入了,所以无非就是用过这些计算,复杂的图像复杂的计算来的出这些图像的位置或者大小,呈现的xyz轴坐标,达到显示的目的,这就是OpenGL中的数学应用了。

(补充)

现在我们涉及另外两个矩阵,一个是model矩阵,一个是view矩阵,外加上我们知道的projection矩阵,
这三个矩阵就是MVP矩阵,而且通常就是以MVP的顺序来进行变换的。

我们可以想象一下这个渲染过程
首先,我们并没有图,然后我们有了一个立方体的顶点数组,这个时候,我们要建模,对吧,先要把立方体这些顶点先画出来,然后这个时候,如果这个立方体要变化了呢,在这个过程中要用到model矩阵进行变换,我概括为物体自己动,然后就是view矩阵,你可以把view矩阵当成一个相机,相机在左边看一个立方体和在右边看一个立方体,是不是会不一样,这个时候我们相当于要画一个立方体的左侧视图和右侧视图,这种变换就需要用到view矩阵,我概括为我们人的视角动,最后就是投影矩阵了,前面已经说过了,投影矩阵就是建立起一个标准的坐标系,让我们的立方体投影到对应的位置上去,而不是东一块西一块,这就是投影矩阵的作用,我概括为OpenGL要把画面打在2D的屏幕上面。

三、OpenGL中的三种变换矩阵

在OpenGL中,MVP(Model-View-Projection)矩阵是一种用于进行3D图形变换的常见矩阵组合。下面是它们的作用分别:

Model Matrix(模型矩阵):作用: 用于将模型的局部坐标系转换为世界坐标系。模型矩阵包含了平移、旋转和缩放等变换,使得模型可以在世界空间中正确定位和变换。
公式: FinalPosition = ModelMatrix * VertexPosition


View Matrix(视图矩阵):作用: 用于定义观察者的视角和位置,将世界坐标系中的物体变换到相机坐标系。视图矩阵决定了我们从哪个视角观察场景。
公式: CameraSpacePosition = ViewMatrix * WorldSpacePosition


Projection Matrix(投影矩阵):作用: 用于将相机坐标系中的物体变换为裁剪坐标系,进行透视或正交投影。投影矩阵定义了视锥体,将场景投影到裁剪坐标系,最终形成我们看到的屏幕图像。
公式: ClipSpacePosition = ProjectionMatrix * CameraSpacePosition


MVP Matrix(Model-View-Projection 矩阵):作用: 将模型、视图和投影矩阵组合在一起,用于将局部坐标系的模型变换到屏幕空间。MVP矩阵是通过将模型矩阵、视图矩阵和投影矩阵相乘得到的。
公式: ClipSpacePosition = MVPMatrix * VertexPosition

总体而言,MVP矩阵的应用是将3D场景中的对象正确变换和投影到屏幕上,使得它们在屏幕上正确可视化。这些矩阵的组合和使用是3D图形渲染中的基本步骤。

proj * view * model矩阵是这样然后* position的,所以真正运算是先model再view再projecttion的,而在数学类中,这个vec不是矩阵,是靠translate转换为矩阵的

glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(200, 200, 0));

这样就比我们纯写矩阵要好,因为这样我们看看

//声明一个矩阵,用于view矩阵变换
        glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(-100, 0, 0));

这个就是把视角向右移动100,然后观察就知道物体应该向左移动100,我们写成glm::vec3(-100, 0, 0)就很方便

//声明一个矩阵,用于model矩阵变换
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(200, 200, 0));

 这个就是把物体向上向右移动200,是不是看到数据就很直观,然后我们再代码中这样子的矩阵变量传给着色器中的uniform变量矩阵,就可以达到那些平移,投影,变化等等的效果了。

		//声明一个矩阵 正交矩阵用于投影,proj和坐标position相乘,投影在屏幕的对应位置
		glm::mat4 proj = glm::ortho(0.0f, 960.0f, 0.0f, 540.0f, -1.0f, 1.0f);

		//声明一个矩阵,用于view矩阵变换
		glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0));
		
		//声明一个矩阵,用于model矩阵变换
		glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(200, 200, 0));
		//把三种变换融合 proj * view * model矩阵是这样然后* position的,所以真正运算是先model再view再projecttion的
		glm::mat4 mvp = proj * view * model;

		shader.Bind();
		shader.SetUniformMat4f("u_MVP", mvp);


 文章来源地址https://www.toymoban.com/news/detail-773851.html

到了这里,关于一篇搞懂数学在OpenGL中的应用及矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一篇搞懂Java多线程运行机制

    Java是一种支持多线程编程的语言。多线程可以让程序同时执行多个任务,从而提高程序的效率和响应速度。在本篇博客中,我将介绍Java多线程的基础知识,包括线程的创建、启动、中断以及线程同步等方面。 什么是程序? 程序是为完成特定任务,用某种语言编程写的一组指

    2023年04月15日
    浏览(40)
  • 如何理解场外期权交易?个股期权一篇搞懂

    场外期权是一种金融衍生品,指在非集中性的交易场所进行的非标准化的金融期权合约。它是一种买卖双方达成的合约,赋予买方在未来的某一特定日期以特定价格购买或出售一种资产的权利,但不必承担必须履行的义务。下文科普如何理解场外期权交易?个股期权一篇搞懂

    2024年04月24日
    浏览(49)
  • 什么是双向链表,一篇搞懂双向链表

    还不清楚单向链表的同学可以去看我另一篇文章,实践总结:一篇搞懂链表——单链表和双指针技巧 首先,我们先看下双向链表(下文用双链表表述)的图示,见下图: 与单链表不同的是,双链表有两个方向,对应单链表节点中的一个引用字段next,双链表每个节点中都含有

    2024年03月13日
    浏览(41)
  • 基于IIC通信的显示器OLED编程详解(一篇搞懂)

    上一篇博客介绍了IIC通信,这篇我们就来玩玩oled模块。当然选用的是IIC接口,因为市面上还有一种是SPI接口的。对于oled长啥样,采用了什么材料,工艺怎么怎么样等等这里就不作任何介绍,搞得眼花缭乱的,对我们用它做开发也没任何帮助,同时节省读者阅读时间。为什么

    2024年02月09日
    浏览(48)
  • 一篇搞明白微信小程序的基本授权功能

    一、介绍         由于部分接口需要经过用户授权同意才能调用。我们把这些接口按使用范围分成多个  scope  , 用户选择对  scope  来进行授权,当授权给一个  scope  之后,其对应的所有接口都可以直接使用。 此类接口调用时: 如果用户未接受或拒绝过此权限,会弹窗

    2024年01月17日
    浏览(50)
  • LaTeX数学模式中的矩阵

    LaTeX数学模式中的矩阵 上节说明了一些 数学公式初步。 (1)引入 amsmath 宏包。 (2)用中括号引入行间公式。 (3)在LaTeX中,可以使用 matrix 环境实现矩阵的排版。 (4)用于矩阵排版的matrix环境,与用于表格排版的 tabular 环境使用方法非常类似。 我们在环境中随便写一个

    2024年02月01日
    浏览(32)
  • Hessian 矩阵与凸性:从数学理论到实际应用

    在现代计算机科学和人工智能领域,优化问题是非常常见的。这些问题通常涉及到最小化或最大化一个函数,以实现一定的目标。例如,在机器学习中,我们可能需要最小化损失函数以实现模型的训练;在操作研究中,我们可能需要最小化成本函数以实现资源的分配;在信号

    2024年04月27日
    浏览(35)
  • 离散数学及应用 -- 02 基本结构:集合、函数、序列、求和与矩阵

    目录 集合 集合运算 函数(映射、变换) 序列 求和 ​编辑集合的基数 矩阵 集合是对象的一个无序的聚集,对象也称为集合的元素或成员。集合包含它的元素。         ∈A:a是集合A中一个元素         ∉A:a是集合A中一个元素 描述集合的方式:         花名册方

    2024年02月01日
    浏览(43)
  • 【数学与算法】奇异矩阵、奇异值、奇异值分解、奇异性

    我们经常会碰到几个名词很相近的一些数学术语,例如 奇异矩阵、奇异值、奇异值分解、奇异性 ,经常会混淆,这里把它们的定义放在一起,做一下总结: 1.奇异矩阵: 奇异矩阵 是线性代数的概念,就是该矩阵的 秩不是满秩 。 首先,看这个矩阵是不是方阵,即行数和列数

    2024年02月06日
    浏览(42)
  • 一张图搞懂CPU、OpenGL/DirectX、显卡驱动和GPU之间的关系

     openGL和DirectX就是这些图像应用编程接口,这些接口用于渲染二维或三维图形。可以说,这些接口架起了上层应用程序和底层GPU的沟通桥梁。一个应用程序向这些接口发送渲染命令,而这些接口会依次向显卡驱动(Graphics Driver)发送渲染命令,这些显卡驱动是真正知道如何和

    2024年02月13日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包