一区二区三区电影_国产伦精品一区二区三区视频免费_亚洲欧美国产精品va在线观看_国产精品一二三四

聯(lián)系我們 - 廣告服務(wù) - 聯(lián)系電話:
您的當(dāng)前位置: > 關(guān)注 > > 正文

【教程】矩陣相乘時 我們先寫位移再縮放

來源:CSDN 時間:2023-02-03 14:52:15

注意,當(dāng)矩陣相乘時我們先寫位移再寫縮放變換的。建議您在組合矩陣時,先進(jìn)行縮放操作,然后是旋轉(zhuǎn),最后才是位移,否則它們會(消極地)互相影響。比如,如果你先位移再縮放,位移的向量也會同樣被縮放(譯注:比如向某方向移動2米,2米也許會被縮放成1米)!

(一)矩陣變換


(資料圖)

1、添加頭文件

我們需要的GLM的大多數(shù)功能都可以從下面這3個頭文件中找到:

#include#include#include

2、矩陣初始化

GLM庫從0.9.9版本起,默認(rèn)會將矩陣類型初始化為一個零矩陣(所有元素均為0),而不是單位矩陣(對角元素為1,其它元素為0)。如果你使用的是0.9.9或0.9.9以上的版本,你需要將所有的矩陣初始化改為 glm::mat4 mat = glm::mat4(1.0f)。如果你想與本教程的代碼保持一致,請使用低于0.9.9版本的GLM,或者改用上述代碼初始化所有的矩陣。

我們來看看是否可以利用我們剛學(xué)的變換知識把一個向量(1, 0, 0)位移(1, 1, 0)個單位(注意,我們把它定義為一個glm::vec4類型的值,齊次坐標(biāo)設(shè)定為1.0):

glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);// 譯注:下面就是矩陣初始化的一個例子,如果使用的是0.9.9及以上版本// 下面這行代碼就需要改為:// glm::mat4 trans = glm::mat4(1.0f)// 之后將不再進(jìn)行提示glm::mat4 trans;

我們先用GLM內(nèi)建的向量類定義一個叫做vec的向量。接下來定義一個mat4類型的trans,默認(rèn)是一個4×4單位矩陣。

3、變換

我們來做些更有意思的事情,讓我們來旋轉(zhuǎn)和縮放之前教程中的那個箱子。首先我們把箱子逆時針旋轉(zhuǎn)90度。然后縮放0.5倍,使它變成原來的一半大。隨時間變化,使用GLFW的時間函數(shù)來獲取不同時間的角度

glm::mat4 trans;trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));

首先,我們把箱子在每個軸都縮放到0.5倍,然后沿z軸旋轉(zhuǎn)90度。GLM希望它的角度是弧度制的(Radian),所以我們使用glm::radians將角度轉(zhuǎn)化為弧度。注意有紋理的那面矩形是在XY平面上的,所以我們需要把它繞著z軸旋轉(zhuǎn)。因為我們把這個矩陣傳遞給了GLM的每個函數(shù),GLM會自動將矩陣相乘,返回的結(jié)果是一個包括了多個變換的變換矩陣。

矩陣傳遞給著色器

我們在前面簡單提到過GLSL里也有一個mat4類型。所以我們將修改頂點著色器讓其接收一個mat4的uniform變量,然后再用矩陣uniform乘以位置向量:

#version 330 corelayout (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);}

GLSL也有mat2和mat3類型從而允許了像向量一樣的混合運算。前面提到的所有數(shù)學(xué)運算(像是標(biāo)量-矩陣相乘,矩陣-向量相乘和矩陣-矩陣相乘)在矩陣類型里都可以使用。當(dāng)出現(xiàn)特殊的矩陣運算的時候我們會特別說明。

變換矩陣傳遞給著色器:

unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));

我們首先查詢uniform變量的地址,然后用有Matrix4fv后綴的glUniform函數(shù)把矩陣數(shù)據(jù)發(fā)送給著色器。第一個參數(shù)你現(xiàn)在應(yīng)該很熟悉了,它是uniform的位置值。第二個參數(shù)告訴OpenGL我們將要發(fā)送多少個矩陣,這里是1。第三個參數(shù)詢問我們我們是否希望對我們的矩陣進(jìn)行置換(Transpose),也就是說交換我們矩陣的行和列。OpenGL開發(fā)者通常使用一種內(nèi)部矩陣布局,叫做列主序(Column-major Ordering)布局。GLM的默認(rèn)布局就是列主序,所以并不需要置換矩陣,我們填GL_FALSE。最后一個參數(shù)是真正的矩陣數(shù)據(jù),但是GLM并不是把它們的矩陣儲存為OpenGL所希望接受的那種,因此我們要先用GLM的自帶的函數(shù)value_ptr來變換這些數(shù)據(jù)。

(二)畫出立方體

頂點坐標(biāo)

float vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f};

2、繪制圖元

glDrawArrays(GL_TRIANGLES, 0, 36);  //畫三角形,從第 0 個數(shù)據(jù)開始畫,到最后一個數(shù)據(jù)(第 3 個)結(jié)束//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

3、增加深度測試

//glEnable(GL_DEPTH_TEST);  //深度測試//glDepthFunc(GL_LESS);  //深度信息小于當(dāng)期信息,就把進(jìn)行測試

4、在清除屏幕的時候,也需要把深度緩存的數(shù)據(jù)清除掉!

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

附加內(nèi)容:畫出多個立方體

現(xiàn)在我們想在屏幕上顯示10個立方體。每個立方體看起來都是一樣的,區(qū)別在于它們在世界的位置及旋轉(zhuǎn)角度不同。立方體的圖形布局已經(jīng)定義好了,所以當(dāng)渲染更多物體的時候我們不需要改變我們的緩沖數(shù)組和屬性數(shù)組,我們唯一需要做的只是改變每個對象的模型矩陣來將立方體變換到世界坐標(biāo)系中。

首先,讓我們?yōu)槊總€立方體定義一個位移向量來指定它在世界空間的位置。我們將在一個glm::vec3數(shù)組中定義10個立方體位置:

glm::vec3 cubePositions[] = {  glm::vec3( 0.0f,  0.0f,  0.0f),   glm::vec3( 2.0f,  5.0f, -15.0f),   glm::vec3(-1.5f, -2.2f, -2.5f),    glm::vec3(-3.8f, -2.0f, -12.3f),    glm::vec3( 2.4f, -0.4f, -3.5f),    glm::vec3(-1.7f,  3.0f, -7.5f),    glm::vec3( 1.3f, -2.0f, -2.5f),    glm::vec3( 1.5f,  2.0f, -2.5f),   glm::vec3( 1.5f,  0.2f, -1.5f),   glm::vec3(-1.3f,  1.0f, -1.5f)  };

現(xiàn)在,在游戲循環(huán)中,我們調(diào)用glDrawArrays 10次,但這次在我們渲染之前每次傳入一個不同的模型矩陣到頂點著色器中。我們將會在游戲循環(huán)中創(chuàng)建一個小的循環(huán)用不同的模型矩陣渲染我們的物體10次。注意我們也對每個箱子加了一點旋轉(zhuǎn):

glBindVertexArray(VAO);for(unsigned int i = 0; i < 10; i++){  glm::mat4 model;  model = glm::translate(model, cubePositions[i]);  float angle = 20.0f * i;   model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));  ourShader.setMat4("model", model);  glDrawArrays(GL_TRIANGLES, 0, 36);}

這段代碼將會在每次新立方體繪制出來的時候更新模型矩陣,如此總共重復(fù)10次。然后我們應(yīng)該就能看到一個擁有10個正在奇葩地旋轉(zhuǎn)著的立方體的世界。

責(zé)任編輯:

標(biāo)簽:

相關(guān)推薦:

精彩放送:

新聞聚焦
Top 主站蜘蛛池模板: 济宁市| 星座| 水城县| 三河市| 玉环县| 宜宾市| 兰溪市| 和林格尔县| 沈阳市| 宁南县| 扶绥县| 泗水县| 怀柔区| 洛隆县| 新巴尔虎左旗| 黔西县| 开远市| 浦北县| 汤阴县| 永靖县| 墨脱县| 吉安县| 于都县| 翁牛特旗| 溆浦县| 庆城县| 满城县| 凤山市| 开远市| 尼木县| 九寨沟县| 武安市| 隆化县| 南雄市| 冀州市| 张家界市| 泸水县| 定远县| 英德市| 榕江县| 汉源县|