OpenGL學習(六)變換
參考官方文檔https://learnopengl-cn.github.io/
那麼現在有意思的來了。首先關於矩陣運算就不用多做介紹了。直接進入實戰部分。先下載GLM。這個直接百度可以找到:https://github.com/g-truc/glm。(官方文檔中給出的鏈接打不開,只能百度)下載解壓。剛開始我以爲需要用cMake,後面發現不用cMake,只需要在你當前的項目的屬性中添加包含目錄就行了。需要用到的大多數功能都可以在下面3個頭文件中找到。
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
例如:
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<iostream>
int main() {
glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);//創建向量
glm::mat4 trans = glm::mat4(1.0f);//創建一個4*4的單位矩陣
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;//1+1,0+1,0+0=>2,1,0
}
輸出結果爲:
210
C:\Users\xhh\Source\Repos\glmTest\x64\Debug\glmTest.exe (進程 58428)已退出,代碼爲 0。
按任意鍵關閉此窗口. . .
下面我們將再我們前面的窗口的基礎上,運用glm的矩陣來操作窗口的繪圖。
頂點着色器shader.vs
#version 330 core
layout(location=0) in vec3 aPos;
layout(location=1) in vec3 aColor;
layout(location=2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 transform;
void main(){
gl_Position=transform*vec4(aPos.x,aPos.y,aPos.z,1.0);
ourColor=aColor;
TexCoord=vec2(aTexCoord.x,1.0-aTexCoord.y);
}
主程序中main.cpp
...;
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
...;
int main(){
...;
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));
...;
while(...){
...;
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
...;
}
...;
}
這樣對我們的圖案旋轉90度並縮小爲原來的二分之一。像這樣
或者再渲染循環中將舉證創建爲:
glm::mat4 trans = glm::mat4(1.0f);
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));
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
最終運行時會發現窗口中的圖片會不斷的旋轉:
練習:
- 使用應用在箱子上的最後一個變換,嘗試將其改變爲先旋轉,後位移。看看發生了什麼,試着想想爲什麼會發生這樣的事情
改爲:
trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
這時它會繞窗口的中心旋轉而不是箱子的中心旋轉,
爲什麼這兩個操作的順序反過來結果會差別這麼大呢?
這個問題學過量子力學的應該很好理解。其實很簡單的一個問題,前面的代碼是平移在前而旋轉在後,兩個操作平移記爲T,旋轉記爲R,作用到向量X上,TRX
,所以實際上是先繞窗口中心旋轉然後再平移到右下角。而現在就是反過來,先平移到右下角然後再繞中心旋轉。旋轉角度是隨時間增大的,所以實際上就變成這樣了。
- 嘗試再次調用glDrawElements畫出第二個箱子,只使用變換將其擺放在不同的位置。讓這個箱子被擺放在窗口的左上角,並且會不斷的縮放(而不是旋轉)。(
sin
函數在這裏會很有用,不過注意使用sin
函數時應用負值會導致物體被翻轉)
第二個箱子,再渲染循環中接着前面的glDrawElements來,代碼如下:
//第二個箱子
trans = glm::translate(glm::mat4(1.0f), glm::vec3(-0.5f, 0.5f, 0.0f));
trans = glm::scale(trans, glm::vec3(abs(sin((float)(glfwGetTime()))),abs(sin((float)glfwGetTime())), 1.0f));
transformLoc = glGetUniformLocation(ourShader.ID, "transform");
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
ourShader.use();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
很順利的得到了想要的結果了,它會隨時間縮小幅度變化: