1. 程式人生 > >Opengl-變換&矩陣

Opengl-變換&矩陣

向量

定義: 向量是一個既有大小又有方向的量(聯絡位移和速度的概念)

理解向量把握:

  • 向量的大小就是向量的長度(模),向量的長度非負
  • 向量的方向描述了向量的指向
  • 向量是沒有位置的,與點是不同的
  • 向量與標量不同,變數是隻有大小而沒有方向的量,例如位移是向量,而距離是標量

Alt

向量與標量運算

標量(Scalar) 只是一個數字(或者說是僅有一個分量的向量)。當把一個向量加/減/乘/除一個標量,我們可以簡單的把向量的每個分量分別進行該運算。對於加法來說會像這樣:

Alt

向量取反

對一個 向量取反(Negate) 會將其 方向逆轉

Alt

向量加減

向量的加法 可以被定義為是 分量的(Component-wise)相加

,即將一個向量中的每一個分量加上另一個向量的對應分量

Alt

向量的減法 等於加上第二個向量的 相反向量

Alt

三角形法則 Alt

長度

Alt

** 單位向量(Unit Vector)** : 單位向量有一個特別的性質——它的長度是1

任意向量的每個分量除以向量的長度得到它的單位向量n:

Alt

我們把這種方法叫做一個 向量的標準化(Normalizing)。單位向量頭上有一個^樣子的記號,通常單位向量會變得很有用,特別是在我們只關心方向不關心長度的時候(如果改變向量的長度,它的方向並不會改變)。

向量點乘

點積有兩種定義方式:代數方式 和 **幾何方式 **

代數定義

Alt

幾何定義

Alt

應用: 使用點乘可以很容易測試兩個向量是否 正交(Orthogonal)

平行(正交意味著兩個向量互為直角);

可以快速計算出兩個向量的 夾角

Alt

叉乘

叉乘只在 3D空間 中有定義,它需要兩個 不平行向量 作為輸入,生成一個 正交 於兩個輸入向量的第三個向量

Alt

注意叉乘結果的方向需要根據 右手規則 來確定。所謂右手規則是指,將向量a與b放在同一個起點時,當右手的四個手指從a所指方向轉到b所指方向握拳時,大拇指的指向即為a×b的方向

Alt

幾何意義 叉乘的模可以視為以a和b為兩邊的平行四邊形的面積,

其中|b|sinθ可以視為平行四邊形的高,計算後a×b的模即為平行四邊形的面積 Alt

矩陣的概念

Alt

行向量和列向量

Alt

矩陣加減法

Alt

標量和矩陣乘法

Alt

矩陣和矩陣乘法

Alt

注意矩陣乘法不滿足交換律 一般而言矩陣乘積AB≠BA(當然存在特殊情況下滿足,逆矩陣相乘為單位矩陣),因此在OpenGL中應用變換矩陣時注意變換應用的順序。

矩陣與向量相乘

矩陣和向量相乘是矩陣和矩陣相乘的特例,給定矩陣A和列向量v

Alt

單位矩陣

單位矩陣是一個除了對角線以外都是0的 N×N 矩陣

Alt

縮放

Alt

位移

Alt

齊次座標(Homogeneous Coordinates)

向量的w分量也叫 齊次座標 。想要從齊次向量得到3D向量,我們可以把x、y和z座標分別除以w座標。我們通常不會注意這個問題,因為w分量通常是1.0。使用齊次座標有幾點好處:它允許我們在3D向量上進行位移(如果沒有w分量我們是不能位移向量的),而且下一章我們會用w值建立3D視覺效果。

如果一個向量的齊次座標是0,這個座標就是方向向量(Direction Vector),因為w座標是0,這個向量就不能位移(譯註:這也就是我們說的不能位移一個方向)。

旋轉

Alt

在3D空間中旋轉需要定義一個 和一個 旋轉軸(Rotation Axis)。物體會沿著給定的旋轉軸旋轉特定角度

Alt

萬能公式 其中(Rx,Ry,Rz)代表任意旋轉軸: Alt

旋轉矩陣推導https://blog.csdn.net/u012763833/article/details/52605747

實踐

GLM

GLM是OpenGL Mathematics的縮寫,它是一個 只有標頭檔案 的庫,擁有絕大多數的矩陣操作功能

glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
glm::mat4 trans;
trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
vec = trans * vec;
std::cout << vec.x << vec.y << vec.z << std::endl;

glm::mat4 trans;
trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
trans = glm::scale(trans, glm::vec3(0.5, 0.5, 0.5));

把矩陣傳遞給著色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(aPos, 1.0f);
    TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);
}
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
  • 第一個引數,它是uniform的位置值
  • 第二個引數告訴OpenGL我們將要傳送多少個矩陣,這裡是1
  • 三個引數詢問我們我們是否希望對我們的矩陣進行置換(Transpose),OpenGL開發者通常使用一種內部矩陣佈局,叫做列主序(Column-major Ordering)佈局。GLM的預設佈局就是列主序
  • 最後一個引數是真正的矩陣資料,矩陣首地址