Opengl-變換&矩陣
向量
定義: 向量是一個既有大小又有方向的量(聯絡位移和速度的概念)
理解向量把握:
- 向量的大小就是向量的長度(模),向量的長度非負
- 向量的方向描述了向量的指向
- 向量是沒有位置的,與點是不同的
- 向量與標量不同,變數是隻有大小而沒有方向的量,例如位移是向量,而距離是標量
向量與標量運算
標量(Scalar) 只是一個數字(或者說是僅有一個分量的向量)。當把一個向量加/減/乘/除一個標量,我們可以簡單的把向量的每個分量分別進行該運算。對於加法來說會像這樣:
向量取反
對一個 向量取反(Negate) 會將其 方向逆轉
向量加減
向量的加法 可以被定義為是 分量的(Component-wise)相加
向量的減法 等於加上第二個向量的 相反向量
三角形法則
長度
** 單位向量(Unit Vector)** : 單位向量有一個特別的性質——它的長度是1
任意向量的每個分量除以向量的長度得到它的單位向量n:
我們把這種方法叫做一個 向量的標準化(Normalizing)。單位向量頭上有一個^樣子的記號,通常單位向量會變得很有用,特別是在我們只關心方向不關心長度的時候(如果改變向量的長度,它的方向並不會改變)。
向量點乘
點積有兩種定義方式:代數方式 和 **幾何方式 **
代數定義
幾何定義
應用: 使用點乘可以很容易測試兩個向量是否 正交(Orthogonal)
可以快速計算出兩個向量的 夾角
叉乘
叉乘只在 3D空間 中有定義,它需要兩個 不平行向量 作為輸入,生成一個 正交 於兩個輸入向量的第三個向量
注意叉乘結果的方向需要根據 右手規則 來確定。所謂右手規則是指,將向量a與b放在同一個起點時,當右手的四個手指從a所指方向轉到b所指方向握拳時,大拇指的指向即為a×b的方向
幾何意義 叉乘的模可以視為以a和b為兩邊的平行四邊形的面積,
其中|b|sinθ可以視為平行四邊形的高,計算後a×b的模即為平行四邊形的面積
矩陣的概念
行向量和列向量
矩陣加減法
標量和矩陣乘法
矩陣和矩陣乘法
注意矩陣乘法不滿足交換律 一般而言矩陣乘積AB≠BA(當然存在特殊情況下滿足,逆矩陣相乘為單位矩陣),因此在OpenGL中應用變換矩陣時注意變換應用的順序。
矩陣與向量相乘
矩陣和向量相乘是矩陣和矩陣相乘的特例,給定矩陣A和列向量v
單位矩陣
單位矩陣是一個除了對角線以外都是0的 N×N 矩陣
縮放
位移
齊次座標(Homogeneous Coordinates)
向量的w分量也叫 齊次座標 。想要從齊次向量得到3D向量,我們可以把x、y和z座標分別除以w座標。我們通常不會注意這個問題,因為w分量通常是1.0。使用齊次座標有幾點好處:它允許我們在3D向量上進行位移(如果沒有w分量我們是不能位移向量的),而且下一章我們會用w值建立3D視覺效果。
如果一個向量的齊次座標是0,這個座標就是方向向量(Direction Vector),因為w座標是0,這個向量就不能位移(譯註:這也就是我們說的不能位移一個方向)。
旋轉
在3D空間中旋轉需要定義一個 角 和一個 旋轉軸(Rotation Axis)。物體會沿著給定的旋轉軸旋轉特定角度
萬能公式 其中(Rx,Ry,Rz)代表任意旋轉軸:
旋轉矩陣推導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的預設佈局就是列主序
- 最後一個引數是真正的矩陣資料,矩陣首地址